3.4 Diagnose Leaks in Java Language Code
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.
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.
3.4.1 Create a Heap Dump
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.
$ 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 the JAVA_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. |
jcmd GC.heap_dump filename=Myheapdump
$ jmap -dump:format=b,file=snapshot.jmap pid
3.4.2 Obtain a Heap Histogram
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.
jcmd GC.class_histogram filename=Myheaphistogram
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.
$ 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[] :
3.4.3 Monitor the Objects Pending Finalization
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.
See Finalization and Weak, Soft, and Phantom References in Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide for information about detecting and migrating from finalization.
How to Generate JVM Heap Memory Dump?
Java Heap dump is a snapshot of all java objects that are present in the JVM(Java Virtual Machine) at a certain point in time. The JVM allocates memory for objects which are class instances or arrays in the heap memory. When the objects are no longer needed or are no more referenced, the Garbage Collector runs and reclaims the memory space occupied by these objects.
The heap dump is in binary format, and it has .hprof extension. It can be opened and analyzed using applications like JVisualVM and Eclipse MAT(Memory Analyzer Tool). We generate java memory heap dump to identify issues like memory leaks and to optimize memory usage in our application.
There are different ways of generating a java memory heap dump. JDK comes up with various tools for generating heap dump. These tools are located in bin folder under JDK home directory.. Let us discuss how to generate JVM Heap Dump which is as follows:
- Using jmap command
- Using jcmd command on terminal
- Using the JVisualVM tool
- Identifying HeapDumpOnOutOfMemory
- Using JMX Console
- Using HotSpotDiagnosticMBean by writing a program
Method 1: Using map command
jmap is a command which you run inside the bin folder of your JDK home directory. It gives statistics about memory usage. The structure is as follows:
jmap -dump:[live],format=b,file= live:- This parameter is optional. If set, it prints all those objects that have active references. format = b , which means the heap dump file is in binary format. It is not necessary to set this parameter. file = indicates where the heap dump file will be generated. :- process id of the java process
Now in order to get the process id of a running java process, one can use one of the below options as defined:
We type this command from a Unix terminal or Windows Command prompt where JDK is installed. It gives the process ID of the running java process
This gives the process ID of all running java processes. It works only on a Unix Terminal
1.3 Using task manager application in windows operating systems.
Method 2: Using jcmd command on terminal
This command sends a request to the JVM to generate a heap dump. One of its parameters is GC.heap_dump. It is as shown below:
jcmd GC.heap_dump - Process id of java process - Path where the heap dump is to be generated
Method 3: Using the JVisualVM tool
This is a tool that is packaged within JDK. It helps to monitor and troubleshoot java applications. It has a Graphical User Interface that is simple and intuitive. We type jvisualvm in the start menu, or we go to the bin directory of JDK home directory through command prompt or terminal window in Unix and type jvisualvm
It launches a Java Visual VM application. On the left side, it shows the currently running java process. Right-click the process ID whose heap dump you wish to generate. When we click on heap dump, it generates heap dump for the selected process. Under Basic info, it shows the file path where the heap dump is generated.
Method 4: Identifying HeapDumpOnOutOfMemory
It is ideal to capture heap dumps when an application experiences java.lang.OutOfMemoryError. Heap dumps help identify live objects sitting in the memory and the percentage of memory it occupies.
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=
While running your java application when this system property is set, JVM takes a snapshot of the heap dump when it encounters OutOfMemoryError.
Method 5: Using JMX Console
There is a Hotspot Diagnostic MBean which has a heap dump operation. We use jmx clients like jconsole to invoke the MBean operation. Through JConsole, we can either connect to a local java process or a remote process by specifying the host and port number and username/password. Once we connect to the process id, jconsole applications open with multiple tabs. The Overview tab shows Heap Memory usage, threads, classes, CPU usage
Method 6: Using HotSpotDiagnosticMBean by writing a program
We use HotSpotDiagnosticMBean to invoke the heap dump operation. We get the MBean object from the MBean platform server. In the below example, we have used reflection to invoke the heapDump() method of the MBean object.