Memory

Taking and reading a Java heap dump: jcmd, jmap, HeapDumpOnOutOfMemoryError and Eclipse MAT

Memory · Published 2026-10-21

Rear of a server rack with rows of rack servers and neatly bundled network cables
A heap dump is a snapshot of every object and every reference between them. Photo: Derrick Coetzee, Wikimedia Commons, CC0.

A heap dump is a file containing every object in the Java heap, its fields and the references between objects. It is the most precise tool there is for memory problems, and also the heaviest: taking one pauses the application and the file can contain secrets. This guide covers both sides.

Three ways to get a dump

On demand with jcmd

The JDK troubleshooting guide recommends jcmd over the older jmap. The jcmd reference documents GC.heap_dump with a file name argument and three options: -all to include unreachable objects, -gz to compress with a given level, and -overwrite to replace an existing file.

$ jcmd <pid> GC.heap_dump /var/tmp/app-$(date +%Y%m%d-%H%M).hprof
# compressed, fastest level
$ jcmd <pid> GC.heap_dump -gz=1 /var/tmp/app.hprof.gz

Without -all, only live objects are written, which requires a full collection first. That is usually what you want for leak hunting: dead objects are noise. Use -all when you are investigating allocation churn rather than retention.

The path is resolved by the target JVM, not by your shell, so a relative path lands in the JVM's working directory. Use an absolute path on a disk with enough free space.

With jmap

$ jmap -dump:live,format=b,file=/var/tmp/app.hprof <pid>

The result is equivalent; live plays the same role as omitting -all. If a process is hung and does not answer the attach request, the troubleshooting guide points to jhsdb jmap, which uses the Serviceability Agent instead of the attach mechanism.

Automatically on OutOfMemoryError

The most valuable dump is the one taken at the moment of failure. The java launcher reference documents -XX:+HeapDumpOnOutOfMemoryError (disabled by default) and -XX:HeapDumpPath; without a path the file is written to the working directory as java_pid<pid>.hprof.

-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/var/dumps/
-XX:+ExitOnOutOfMemoryError

-XX:+ExitOnOutOfMemoryError makes the JVM exit after the first OutOfMemoryError, so an orchestrator restarts a clean instance instead of leaving a damaged one serving traffic. The dump is written before the exit. In a container, point HeapDumpPath at a mounted volume, or the file disappears with the container.

What a dump costs

Reading a dump with Eclipse Memory Analyzer

Eclipse Memory Analyzer (MAT) is a free tool that opens HPROF files and builds indexes so that even large dumps can be navigated. On first open it parses the file and writes index files next to it, which makes reopening fast.

Shallow and retained size

Two numbers appear everywhere. Shallow size is the memory of the object itself: its header and fields. Retained size is the memory that would be freed if that object were removed, meaning the object plus everything reachable only through it. A HashMap has a small shallow size and can have an enormous retained size. Leaks are found by retained size.

The views to use, in order

  1. Leak Suspects report. MAT proposes it on opening. It points at objects with a large share of the retained heap and shows the accumulation point. Treat it as a starting hypothesis, not a verdict.
  2. Histogram. Instances and shallow size per class. Sort by retained size (MAT computes it on request) to see which classes matter.
  3. Dominator tree. Objects ordered by retained size, organised so that each object's children are the objects it keeps alive. The top entries are where the memory is.
  4. Path to GC Roots. From a suspicious object, choose Path to GC Roots → exclude weak/soft references. The path shows exactly which chain of fields keeps it alive. See GC roots and memory leaks for how to interpret the root types.

Queries

MAT includes an SQL-like Object Query Language. A query that lists large byte arrays, for example:

SELECT a, a.@length FROM byte[] a WHERE a.@length > 1048576

Comparing two dumps

One dump shows what is big. Two dumps taken some time apart show what is growing, which is the real definition of a leak. MAT can compare histograms between dumps; the classes with the largest increase in instance count are the place to start.

Analysing on a server without a desktop

Large dumps are often easier to analyse where they are produced. MAT ships a headless script that parses a dump and generates reports as zipped HTML:

$ ./ParseHeapDump.sh /var/dumps/java_pid4242.hprof org.eclipse.mat.api:suspects
$ ./ParseHeapDump.sh /var/dumps/java_pid4242.hprof org.eclipse.mat.api:top_components

The index files produced by the headless run can be copied together with the dump and opened later in the desktop tool without re-parsing.

Lighter alternatives first

Not every memory question needs a full dump:

And if the heap is fine but the process is still too big, the problem is outside the heap: direct buffers, Metaspace or other native memory.

Sources