JVM guide

Heap Dump Analysis: From OutOfMemoryError to Root Cause

A heap dump is a snapshot of every object in the JVM's heap at a moment in time. When memory grows or the process dies with OutOfMemoryError, the dump is the definitive evidence: which objects exist, how big they are, and what keeps them alive.

This guide walks the full path — enabling automatic dumps, capturing manually, opening in Eclipse MAT, and turning a 'could be a leak' into a named class, an allocation site, and a fix.

Enable automatic dump on OOM

Best insurance: tell the JVM to dump the heap the moment it dies from OOM, so you always have a forensic artifact.

java -Xmx2g \
  -XX:+HeapDumpOnOutOfMemoryError \
  -XX:HeapDumpPath=/var/log/app.hprof \
  -jar app.jar

Capture manually with jmap/jcmd

Useful for investigating high heap before it OOMs. Find the PID, then dump live (reachable) objects.

jps -l
jcmd <pid> GC.heap_dump /tmp/heap.live.hprof
# or
jmap -dump:live,file=/tmp/heap.live.hprof <pid>

Open and read with Eclipse MAT

Launch MAT and File > Open Heap Dump. Start with the Overview > Leak Suspects, then drill into the Dominator Tree and Path to GC Roots.

# Launch MAT
MemoryAnalyzer /tmp/heap.live.hprof

Find the leak with a 2-dump diff

The classic trick: dump at T1 and T2 over a growing window. If a class's retained size roughly doubles with your growth rate, you've located the accumulation.

jcmd <pid> GC.heap_dump /tmp/h1.hprof
# ... run the workload ...
jcmd <pid> GC.heap_dump /tmp/h2.hprof
# In MAT: compare the Histograms or use the 'Compare' delta tool

Write an OQL query

OQL filters instances when the reports are too broad — e.g., list all your cache entries over a size threshold.

SELECT * FROM com.example.CacheEntry o WHERE o.@retainedHeapSize > 1048576

Frequently asked questions

Live vs full dump — which do I capture?

Live (reachable) is smaller and shows what the app is actually holding. Full includes finalizable/garbage candidates and is used to inspect unreachable-but-uncollected objects. Start with live.

Heap dump causes a pause — is that OK?

Capturing opens the object graph, which adds memory pressure and can cause GC pauses. On production, prefer -XX:+HeapDumpOnOutOfMemoryError (only fires at death) or schedule a manual capture.

What if the dump is huge and MAT runs out of heap?

Raise MAT's own -Xmx in MemoryAnalyzer.ini (e.g., -Xmx8g), and capture live dumps to keep the file manageable.

Last updated August 2026 · JVM Tools is independent and not affiliated with Oracle.