Medium java java-21

How do you optimize memory usage in a Java application?

The 30 second answer

I measure before changing anything: heap used after garbage collection, plus a heap dump and a class histogram to see what's really taking space. Then I fix leaks like unbounded caches, static maps, listeners that are never removed, and thread locals never cleared. I stream large data instead of loading it all, use leaner data structures, and size the heap from measured live data, including container limits.

Measure:

jcmd <pid> GC.class_histogram            # which classes use the most memory
jcmd <pid> GC.heap_dump /tmp/app.hprof   # analyze in Eclipse MAT or VisualVM
-XX:+HeapDumpOnOutOfMemoryError          # capture the moment it fails

Look at retained size and the path to GC roots of the biggest objects.

Common fixes:

  • Leaks: caches without size or TTL limits, static collections, unremoved listeners, ThreadLocal values in pooled threads without remove().
  • Large data: stream from the database or files (pagination, cursors) instead of loading everything with findAll().
  • Overhead: boxed collections like List<Integer> versus int[], oversized initial capacities, duplicate strings (G1 supports -XX:+UseStringDeduplication).
  • Sizing: set -Xmx from live data after a full GC, plus headroom.

[Opinion] In containers prefer -XX:MaxRAMPercentage (for example 70 to 75) over a fixed -Xmx, and leave room for native memory: thread stacks, Metaspace, direct buffers and the code cache.

Sources: jcmd (GC.heap_dump, GC.class_histogram), Troubleshooting Guide: Memory Leaks, java command options

Sources (0)
See inline citations in the answer above.