1. Introduction
In this article, we’ll show different ways to capture a heap dump in Java.
A heap dump is a snapshot of all the objects that are in memory in the JVM at a certain moment. They are very useful to troubleshoot memory-leak problems and optimize memory usage in Java applications.
Heap dumps are usually stored in binary format hprof files. We can open and analyze these files using tools like jhat or JVisualVM. Also, for Eclipse users it’s very common to use MAT.
In the next sections, we’ll go through multiple tools and approaches to generate a heap dump and we’ll show the main differences between them.
2. JDK Tools
The JDK comes with several tools to capture heap dumps in different ways. All these tools are located under the bin folder inside the JDK home directory. Therefore, we can start them from the command line as long as this directory is included in the system path.
In the next sections, we’ll show how to use these tools in order to capture heap dumps.
2.1. jmap
jmap is a tool to print statistics about memory in a running JVM. We can use it for local or remote processes.
To capture a heap dump using jmap we need to use the dump option:
jmap -dump:[live],format=b,file=<file-path> <pid>
Along with that option, we should specify several parameters:
- live: if set it only prints objects which have active references and discards the ones that are ready to be garbage collected. This parameter is optional
- format=b: specifies that the dump file will be in binary format. If not set the result is the same
- file: the file where the dump will be written to
- pid: id of the Java process
An example would be like this:
jmap -dump:live,format=b,file=/tmp/dump.hprof 12587
Remember that we can easily get the pid of a Java process by using the jps command.
Keep in mind that jmap was introduced in the JDK as an experimental tool and it’s unsupported. Therefore, in some cases, it may be preferable to use other tools instead.
2.2. jcmd
jcmd is a very complete tool that works by sending command requests to the JVM. We have to use it in the same machine where the Java process is running.
One of its many commands is the GC.heap_dump. We can use it to get a heap dump just by specifying the pid of the process and the output file path:
jcmd <pid> GC.heap_dump <file-path>
We can execute it with the same parameters that we used before:
jcmd 12587 GC.heap_dump /tmp/dump.hprof
As with jmap, the dump generated is in binary format.
2.3. JVisualVM
JVisualVM is a tool with a graphical user interface that lets us monitor, troubleshoot, and profile Java applications. The GUI is simple but very intuitive and easy to use.
One of its many options allows us to capture a heap dump. If we right-click on a Java process and select the “Heap Dump” option, the tool will create a heap dump and open it in a new tab:
Notice that we can find the path of the file created in the “Basic Info” section.
Starting from JDK 9, Visual VM is not included in the Oracle JDK and Open JDK distributions. Therefore, if we’re using Java 9 or newer versions, we can get the JVisualVM from the Visual VM open source project site.
3. Capture a Heap Dump Automatically
All the tools that we’ve shown in the previous sections are intended to capture heap dumps manually at a specific time. In some cases, we want to get a heap dump when a java.lang.OutOfMemoryError occurs so it helps us investigate the error.
For these cases, Java provides the HeapDumpOnOutOfMemoryError command-line option that generates a heap dump when a java.lang.OutOfMemoryError is thrown:
java -XX:+HeapDumpOnOutOfMemoryError
By default, it stores the dump in a java_pid<pid>.hprof file in the directory where we’re running the application. If we want to specify another file or directory we can set it in the HeapDumpPath option:
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<file-or-dir-path>
When our application runs out of memory using this option, we’ll be able to see in the logs the created file that contains the heap dump:
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
Dumping heap to java_pid12587.hprof ...
Exception in thread "main" Heap dump file created [4744371 bytes in 0.029 secs]
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at com.baeldung.heapdump.App.main(App.java:7)
In the example above, it was written to the java_pid12587.hprof file.
As we can see, this option is very useful and there is no overhead when running an application with this option. Therefore, it’s highly recommended to use this option always, especially in production.
Finally, this option can also be specified at runtime by using the HotSpotDiagnostic MBean. To do so, we can use JConsole and set the HeapDumpOnOutOfMemoryError VM option to true:
We can find more information about MBeans and JMX in this article.
4. JMX
The last approach that we’ll cover in this article is using JMX. We’ll use the HotSpotDiagnostic MBean that we briefly introduced in the previous section. This MBean provides a dumpHeap method that accepts 2 parameters:
- outputFile: the path of the file for the dump. The file should have the hprof extension
- live: if set to true it dumps only the active objects in memory, as we’ve seen with jmap before
In the next sections, we’ll show 2 different ways to invoke this method in order to capture a heap dump.
4.1. JConsole
The easiest way to use the HotSpotDiagnostic MBean is by using a JMX client such as JConsole.
If we open JConsole and connect to a running Java process, we can navigate to the MBeans tab and find the HotSpotDiagnostic under com.sun.management. In operations, we can find the dumpHeap method that we’ve described before:
As shown, we just need to introduce the parameters outputFile and live into the p0 and p1 text fields in order to perform the dumpHeap operation.
4.2. Programmatic Way
The other way to use the HotSpotDiagnostic MBean is by invoking it programmatically from Java code.
To do so, we first need to get an MBeanServer instance in order to get an MBean that is registered in the application. After that, we simply need to get an instance of a HotSpotDiagnosticMXBean and call its dumpHeap method.
Let’s see it in code:
public static void dumpHeap(String filePath, boolean live) throws IOException {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(
server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
mxBean.dumpHeap(filePath, live);
}
Notice that an hprof file cannot be overwritten. Therefore, we should take this into account when creating an application that prints heap dumps. If we fail to do so we’ll get an exception:
Exception in thread "main" java.io.IOException: File exists
at sun.management.HotSpotDiagnostic.dumpHeap0(Native Method)
at sun.management.HotSpotDiagnostic.dumpHeap(HotSpotDiagnostic.java:60)
5. Conclusion
In this tutorial, we’ve shown multiple ways to capture a heap dump in Java.
As a rule of thumb, we should remember to use the HeapDumpOnOutOfMemoryError option always when running Java applications. For other purposes, any of the other tools can be perfectly used as long as we keep in mind the unsupported status of jmap.
As always, the full source code of the examples is available over on GitHub.
From here for Eclipse analyzer.
Eclipse Memory Analyzer (MAT) – Tutorial
This article describes the usage of the Eclipse Memory Analyzer (MAT) to identify memory leaks.
1. Analyzing memory leaks with Eclipse
1.1. The Eclipse Memory Analyser (MAT) tooling
The Eclipse Memory Analyser Tooling (MAT) is a set of plug-ins for the Eclipse IDE which provides tools to analyze heap dumps from Java application and to identify memory problems in the application. This helps the developer to find memory leaks and high memory consumption issues.
It visualizes the references to objects based on Java heap dumps and provides tools to identify potential memory leaks.
1.2. Using heap dumps to get a snapshot of the memory of an application
A heap dump is a snapshot of the complete Java object graph on a Java application at a certain point in time. It is stored in a binary format called HPROF.
It includes all objects, fields, primitive types and object references.
2. Installation
Install Eclipse MAT via the
menu entry. Select the update site of your release from the drop-down box and once its content is downloaded, select General Purpose Tools and its sub-entries Memory Analyzer and Memory Analyzer(Charts).3. Creating heap dumps for Java programs
It is possible to instruct the JVM to create automatically a heap dump in case that it runs out of memory, i.e. in case of a OutOfMemoryError
error. To instruct the JVM to create a heap dump in such a situation, start your Java application with the -XX:+HeapDumpOnOutOfMemoryError option.
Use the
menu entry to open a dialog to select for which process you want to acquire a memory dump.Select the process for a heap dump in the following dialog and press the Finish button.
Alternatively you can also interactively create a heap dump via Eclipse. For this, open the Memory Analysis perspective via
.If you trigger the creation of the heap manually the JVM performs sa garbage collector run before it writes the heap dump.
4. Use the Eclipse Memory Analyzer
4.1. Reviewing a heap dump
After a new heap dump with the .hprof ending has been created, you can open it via a double-click in Eclipse. If you used MAT to create the heap dump, it should be opened automatically.
You may need to refresh your project (F5 on the project). Double-click the file and select the Leak Suspects Report.
The overview page allows you to start the analysis of the heap dump. The dominator tree gives quickly an overview of the used objects.
In the dominator tree you see the references which are hold.
To find which element is holding the reference to this object, select the entry and select Find shortest path to GC root from the context menu.
4.2. Analyzing Android heap dumps with Eclipse
Android allows to create heap dumps of an application’s heap. This heap dump is stored in a binary format called HPROF. To create a heap dump use the Dump HPROF file button in the DDMS Perspective.
The Android heap dump format is similar to the Java heap dump format but not exactly the same. Eclipse MAT can work directly with the Android heap dump format.
5. Example
5.1. Create Project
Create the Java project called com.vogella.mat.first and the com.vogella.mat.first
package. Create the following class.
package com.vogella.mat.first;
import java.util.ArrayList;
import java.util.List;
public class Main {
/**
* @param args
*/
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
while (1<2){
list.add("OutOfMemoryError soon");
}
}
}
5.2. Create heap dump and analysis
In Eclipse add the -XX:+HeapDumpOnOutOfMemoryError to the runtime configuration.
Run the project. It crashes and writes an heap dump.
Open the heap dump in MAT and get familiar with using the MAT tooling.
6. jconsole
You can also interactively create a heap dumps via the jconsole, a tool which is included in the JDK. Type jconsole in the command line to start it.
To allow a Java program the access of jconsole use the -Dcom.sun.management.jmxremote start option.
Use them MBeans | com.sun.management | HotSpotDiagnostics | Operations |DumpHeap .
More info can be found in JConsole and JConsole Tutorial.
The stack is a part of memory that contains information about nested method calls down to the current position in the program. It also contains all local variables and references to objects on the heap defined in currently executing methods.
This structure allows the runtime to return from the method knowing the address whence it was called, and also clear all local variables after exiting the method. Every thread has its own stack.
The heap is a large bulk of memory intended for allocation of objects. When you create an object with the new keyword, it gets allocated on the heap. However, the reference to this object lives on the stack.
Let’s quickly summarize the differences between the Stack Memory and the Heap Space:
Parameter | Stack Memory | Heap Space |
---|---|---|
Application | Stack is used in parts, one at a time during execution of a thread | The entire application uses Heap space during runtime |
Size | Stack has size limits depending upon OS and is usually smaller then Heap | There is no size limit on Heap |
Storage | Stores only primitive variables and references to objects that are created in Heap Space | All the newly created objects are stored here |
Order | It is accessed using Last-in First-out (LIFO) memory allocation system | This memory is accessed via complex memory management techniques that include Young Generation, Old or Tenured Generation, and Permanent Generation. |
Life | Stack memory only exists as long as the current method is running | Heap space exists as long as the application runs |
Efficiency | Comparatively much faster to allocate when compared to heap | Slower to allocate when compared to stack |
Allocation/Deallocation | This Memory is automatically allocated and deallocated when a method is called and returned respectively | Heap space is allocated when new objects are created and deallocated by Gargabe Collector when they are no longer referenced |