|
Using WDB to examine backtraces in Java™ thread stacks
You can now use HP's debugger WDB 3.0.01 or later (the GNU Debugger GDB) to examine backtraces containing mixed language frames (Java™ and C/C++) in Java™ thread stacks. This will simplify debugging the VM and Java™ mixed-language applications. Set the environment variable GDB_JAVA_UNWINDLIB to the path name of the Java™ Unwind Shared Library libjunwind.sl (PA), which is in the SDK.
The default location of the Java™ Unwind Library in the SDK is shown below. The examples are for SDK 1.4. If you are using JDK 5.0, you would substitute "java1.5" for "java1.4".
/opt/java1.4/jre/lib/PA_RISC/server/libjunwind.sl
/opt/java1.4/jre/lib/PA_RISC2.0/server/libjunwind.sl
/opt/java1.4/jre/lib/PA_RISC2.0W/server/libjunwind.sl
/opt/java1.4/jre/lib/IA64N/server/libjunwind.so
/opt/java1.4/jre/lib/IA64W/server/libjunwind.so
Here are a few examples. In ksh, you would set the environment variable like this:
For 64-bit PA2.0 machines:
export export GDB_JAVA_UNWINDLIB=/opt/java1.4/jre/lib/\
PA_RISC2.0W/server/libjunwind.sl
For 64-bit Itanium 2 machines:
export GDB_JAVA_UNWINDLIB=/opt/java1.4/jre/lib/\
IA64W/server/libjunwind.so
If you installed the SDK in a location other than the default, you would substitute the non-default location for
"/opt/java1.4" in the above commands. Then use WDB as usual to debug your Java™ applications or core files. See the
Java™ Performance tutorial slides for help on how to use the new Java™ stack unwind functionality.
Launching the Java™ application VM manually when debugging
(excerpted from http://java.sun.com/products/jpda/readme.html)
If you are running the version of jdb provided in this release, the application VM is launched for you with the debugger loaded at the back end. However, in the following cases, you will be launching your own application VM, either by hand or in your implementation.
-
Remote debugging with the -attach or -listen jdb option.
-
You are implementing a debugger which uses the JDWP directly.
-
You are implementing a debugger back end which uses JVMDI.
Currently, the first two cases require a command line like the following:
java -Xdebug -Xnoagent -Djava.compiler=NONE
-Xrunjdwp:transport=dt_socket,server=y,suspend=y
-classpath class-path class-name
The -Xdebug option enables debugging. The -Xnoagent disables the default sun.tools.debug debug Agent. The -Djava.compiler=NONE disables the JIT compiler.
For the third case, you must use the same command line options as described above, but you are free to use your own mechanism for loading the JVMDI client into the application VM. You do not need to use -Xrun.
The Connection and Invocation Details document at http://java.sun.com/products/jpda/doc/conninv.html contains more information on necessary VM invocation options and sub-options of -Xrunjdwp.
Diagnosing memory leaks
Java™ applications may be susceptible to two kinds of memory leaks, those in the Java™ heap or in the C heap. If you see a java.lang.OutOfMemoryError, the exception text may be helpful in determining what is happening, but not always. You may find it helpful to read about the java memory layout to get an overall understanding of application memory.
First of all, let your application run long enough to get to a steady state under a representative workload. With the HotSpot JVM, it often takes about 10 minutes under load for the runtime to get warmed up for maximum performance, so you should wait at least this long before measuring anything. To determine if the leak is in the Java™ heap, first run your application with the extra option:
-Xverbosegc:file=<name>
This writes garbage collection and heap size statistics to the file. You can use
HPjtune to view this file and see the heap contents during the run as a graph. If you find the old space continuously grows, you can suspect a Java™ heap leak. Next run the application with:
-classic -Xrunhprof:heap=dump
You must use a heap size of around 256 to 384MB in order for the dump to be written correctly, but the data is perfectly valid and the information applies equally to running under HotSpot. The algorithm for the heap dump requires it to mmap() a new region almost as big as the heap itself to process the data. The classic JVM only can support 1GB of total writable data, so you have to keep the heap small enough to fit two of them in there, and leave some extra space for the C heap.
When you exit the process gracefully at the end of the run, the heap contents are written to the file java.hprof.txt. You can view this file with
HPjmeter.
We recommend you make a short and a long run. You can compare the two runs in HPjmeter, and view the residual objects. Generally the lingering objects will percolate to the top of the residual objects histogram, especially if the difference in run duration is large enough or the leak rate is very high. Then you can look for objects of this type in the Reference Graph. Following the graph from a candidate leaked object back towards the root, you can see how that object is referenced by the application.
To determine if the application is leaking in the C heap, this can be easily observed with GlancePlus in the Process Memory Regions window. The C heap is shown as the DATA region. If the DATA region is continuously growing even after an extended period of time at the steady load state, it may be a C heap memory leak.
There are several possible causes for a C heap leak with a java application:
-
Leak in user JNI native methods
-
Leak caused by a backlog of unexecuted java finalizers which hold on to C memory
-
Leak in JDK code itself
If you have native methods in your application, including Type 2 JDBC drivers from third party vendors, you can use the HP gdb memory leak detection capability. This functionality has been extensively used with the JDK itself and we find it very reliable.
Leaks caused by unexecuted finalizers can be tricky to detect. Many java classes that use finalizers do so to free memory allocated in the C heap. Since execution of finalizers is generally slower than creation of new objects, it is possible in some situations to fill up the C heap with yet-to-be-finalized java-related memory allocations, which may cause other parts of the application or JDK to fail. Finalizers are not executed synchronously during garbage collections. You can measure the finalization with -Xrunhprof:heap=dump then use the Reference Graph in HPjmeter to see what is unfinalized.
If all else fails and you still see a leak, it is occasionally possible to discover a leak in the JDK. You should contact your HP Response Center to report it.
With our combination of tools including GlancePlus, HPjmeter, and HPjtune no memory leak can evade detection for long!
Java™ and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries. Hewlett-Packard is independent of Sun Microsystems, Inc.
|