Our goal is reducing or fixing physical memory allocation (RES in top).

Get a high-level overview

See a summary of memory reservations and allocations in /proc/PID/stats.

Inspecting a process's memory map

Get breakdown of memory map with pmap -x PID:

  • Some will be memory mapped files.
  • anon entries are allocated memory.

Similar data is available in /proc/PID/smaps.

Native memory tracking

The JVM can natively track allocations with -XX:NativeMemoryTracking=[summary|detail]. This tracks allocations only by the JVM, not JNI.

This comes at some cost:

  • Consumes 2 words per malloc
  • 5-10% performance overhead

These metrics can be accessed with either -XX:+PrintNMTStatistics, disabled by default, or jcmd PID vm.native_memory:

  • Total
  • Heap
  • GC tracks GC overhead (e.g. the G1 heap region size)
  • Class
  • Code - code cache (nmethods)
  • Compiler

Initial heap size is not minimum heap size

When setting initial and maximum heap size to the same value:

  • Consider setting -XX:+AlwaysPreTouch to allocate all pages on startup and avoid later page faults and heap resizes.
  • Set -XX:-AdaptiveSizePolicy to prevent adaptive resizing of the heap between MinHeapFreeRatio and MaxHeapFreeRatio. Note that how aggressively memory is freed depends on the selected GC.

Compressed class space

Running out of class space manifests itself as an exception: java.lang.OutOfMemoryError: Compressed class space.

  • jcmd PID VM.classloader_stats prints loaded classes by type (e.g. generator).
  • jcmd PID GC.class_stats prints a breakdown of memory by class.