Diagnosing leaks in Java language code can be difficult. Usually, it requires very detailed knowledge of the application. In addition, the process is often iterative and lengthy. This section provides information about the tools you can use to diagnose memory leaks in Java language code.
Note: Besides the tools mentioned in this section, a large number of third-party memory debugger tools are available. The Eclipse Memory Analyzer Tool (MAT), YourKit (www.yourkit.com) are two examples of commercial tools with memory debugging capabilities. There are many others, and no specific product is recommended. |
The following are two utilities used to diagnose leaks in Java language code.
The NetBeans Profiler: The NetBeans Profiler can locate memory leaks very quickly. Commercial memory leak debugging tools may take a long time to locate a leak in a large application. The NetBeans Profiler, however, uses the pattern of memory allocations and reclamations that such objects typically demonstrate. This process includes also the lack of memory reclamations. The profiler can check where these objects were allocated, which often is sufficient to identify the root cause of the leak.
For more details, see NetBeans Profiler.
The jhat utility: The jhat
utility is useful when debugging unintentional object retention (or memory leaks). It provides a way to browse an object dump, view all reachable objects in the heap, and understand which references are keeping an object alive.
To use jhat
you must obtain one or more heap dumps of the running application, and the dumps must be in binary format. After the dump file is created, it can be used as input to jhat
. See The jhat Utility.
The following sections describe the other ways to diagnose leaks in Java language code.
A heap dump provides detailed information about the allocation of heap memory. There are several ways to create a heap dump:
HPROF can create a heap dump if it is launched with the application. Example 3-1 shows the usage of the command.
Example 3-1 Launch HPROF with the Application
$ java -agentlib:hprof=file=snapshot.hprof,format=b application
Note: If the JVM is embedded or is not started using a command-line launcher that allows additional options to be provided, then it might be possible to use theJAVA_TOOLS_OPTIONS environment variable so that the -agentlib option is automatically added to the command line. See The JAVA_TOOL_OPTIONS Environment Variable for further information about this environment variable. |
When the application is running with HPROF, a heap dump can be created by pressing Control+\ or Control+Break (depending on the platform) in the application console. An alternative approach on Oracle Solaris and Linux operating systems is to send a QUIT signal with the kill -QUIT
pid command. When the signal is received, a heap dump is created for the process with the specified PID; in the preceding example, the file snapshot.hprof
will be created.
The heap dump file contains all the primitive data and stack traces.
A dump file can contain multiple heap dumps. If Control+\ or Control+Break is pressed a number of times then subsequent dumps are appended to the file. The jhat
utility uses the #n
syntax, to distinguish the dumps, where n
is the dump number. See HPROF.
The jmap
utility can be used to create a heap dump of a running process.
It is recommended to use the latest utility, jcmd
instead of jmap
utility for enhanced diagnostics and reduced performance overhead. See Useful Commands for jcmd Utility. The command in Example 3-2 creates a heap dump for a running process using jcmd
and results similar to the jmap
command inExample 3-3.
Example 3-2 Create a Heap Dump using jcmd
jcmd <process id/main class> GC.heap_dump filename=Myheapdump
Regardless of how the JVM was started, the jmap
tool produces a head dump snapshot in the preceding example in a file named snapshot.jmap
. The jmap
output files should contain all the primitive data, but will not include any stack traces showing where the objects have been created. See The jmap Utility.
Another way to create a heap dump is by using the JConsole utility. In the MBeans tab, select the HotSpotDiagnostic MBean, then the Operations display, and choose the dumpHeap operation.
If you specify the -XX:+HeapDumpOnOutOfMemoryError
command-line option while running your application, then when an OutOfMemoryError
exception is thrown, the JVM will generate a heap dump.
You can try to quickly narrow down a memory leak by examining the heap histogram. It can be obtained in several ways:
If the Java process is started with the -XX:+PrintClassHistogram
command-line option, then the Control+Break handler will produce a heap histogram.
You can use the jmap
utility to obtain a heap histogram from a running process:
It is recommended to use the latest utility, jcmd
instead of jmap
utility for enhanced diagnostics and reduced performance overhead. See Useful Commands for jcmd Utility.The command in Example 3-4 creates a heap histogram for a running process using jcmd
and results similar to the following jmap
command.
Example 3-4 Create a Heap Histogram using jcmd
jcmd <process id/main class> GC.class_histogram filename=Myheaphistogram
jmap -histo pid
The output shows the total size and instance count for each class type in the heap. If a sequence of histograms is obtained (for example, every 2 minutes), then you might be able to observe a trend that can lead to further analysis.
You can use the jmap
utility to obtain a heap histogram from a core file as shown in Example 3-5.
For example, if you specify the -XX:+HeapDumpOnOutOfMemoryError
command-line option while running your application, then when an OutOfMemoryError
exception is thrown, the JVM will generate a heap dump. You can then execute jmap
on the core file to get a histogram, as shown in Example 3-6.
Example 3-6 Execute jmap on the Core File
$ jmap -histo \ /java/re/javase/6/latest/binaries/solaris-sparc/bin/java core.27421
Attaching to core core.27421 from executable
/java/re/javase/6/latest/binaries/solaris-sparc/bin/java, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 1.6.0-beta-b63
Iterating over heap. This may take a while...
Heap traversal took 8.902 seconds.
Object Histogram:
Size Count Class description
-------------------------------------------------------
86683872 3611828 java.lang.String
20979136 204 java.lang.Object[]
403728 4225 * ConstMethodKlass
306608 4225 * MethodKlass
220032 6094 * SymbolKlass
152960 294 * ConstantPoolKlass
108512 277 * ConstantPoolCacheKlass
104928 294 * InstanceKlassKlass
68024 362 byte[]
65600 559 char[]
31592 359 java.lang.Class
27176 462 java.lang.Object[]
25384 423 short[]
17192 307 int[]
:
Example 3-6 shows that the OutOfMemoryError
exception was caused by the number of java.lang.String
objects (3,611,828 instances in the heap). Without further analysis it is not clear where the strings are allocated. However, the information is still useful. To continue investigation with tools such as HPROF
and jhat
to find where the strings are allocated, as well as what references are keeping them alive and preventing them from being garbage collected.
When the OutOfMemoryError exception is thrown with the "Java heap space" detail message, the cause can be excessive use of finalizers. To diagnose this, you have several options for monitoring the number of objects that are pending finalization:
The JConsole management tool can be used to monitor the number of objects that are pending finalization. This tool reports the pending finalization count in the memory statistics on the Summary tab pane. The count is approximate, but it can be used to characterize an application and understand if it relies a lot on finalization.
On Oracle Solaris and Linux operating systems, the jmap
utility can be used with the -finalizerinfo
option to print information about objects awaiting finalization.
An application can report the approximate number of objects pending finalization using the getObjectPendingFinalizationCount
method of the java.lang.management.MemoryMXBean
class. Links to the API documentation and example code can be found in Custom Diagnostic Tools. The example code can easily be extended to include the reporting of the pending finalization count.