Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Java heap diagnostics: retained objects, histograms and a controlled dump

Last updated: 29 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A heap histogram counts objects by class, while a heap dump records object state and references needed to investigate why particular objects remain reachable.

Download Java source kit

Java 21+. The program uses JDK classes and requires no preview flags.

Capture a JVM you own

The fixture retains fifty receipt entries through one static list. Each entry owns a small byte array. The static field is an identifiable retention path; an increasing allocation count alone would not explain why an object survives collection.

Run the downloaded diagnostic script against the fixture it starts, rather than attaching to an arbitrary application PID. It collects a live histogram and heap dump using that same JDK’s jcmd, verifies the fixture’s entry count, then stops the fixture and removes its temporary dump. No user process or application secret is inspected.

A histogram can reveal a class growing between captures, but it does not show which reference keeps a particular instance alive. A dump and reference-path analysis answer that second question. The object’s shallow byte count is also different from the memory retained by the reachable subgraph behind it.

Separate the leak hypothesis from evidence

Fifty intentionally retained entries are not a leak. To diagnose a leak, relate retained state to the application’s intended lifetime, compare captures after comparable work, and identify a path that should have been released. A cache without an eviction policy is one candidate; a live queue carrying unfinished work can be legitimate.

Working program

Java
import java.util.*;
import java.util.concurrent.*;
public class RetainedReceiptFixture {
    static final List<Entry> retained=new ArrayList<>();
    static final class Entry {final byte[] payload=new byte[1024];}
    public static void main(String[] args)throws Exception{
        for(int i=0;i<50;i++)retained.add(new Entry());
        System.out.println("retained="+retained.size());
        if(args.length==1&&args[0].equals("--inspect")){
            System.out.println("ready");System.out.flush();new CountDownLatch(1).await(30,TimeUnit.SECONDS);
        }
    }
}

Output

Output
retained=50

Costs and boundaries

This fixture retains fifty entries plus their payloads. A histogram or dump can trigger substantial work and pauses; capture it only under an approved operational procedure for a real service. The bundled check covers controlled capture, not a complete graphical retained-size investigation or a production incident.

Common Mistakes

  • Allocated bytes and currently retained bytes are different measurements.
  • A histogram does not expose every retaining reference path.
  • Heap dumps can contain application data; the fixture contains only synthetic bytes.

Read next

Reachability, Collection observations, Weak lifetime.

java
heap-dump-workflow
Storage details