Understanding the JVM memory

Stumbled upon a very nice explanation of the JVM memory, including garbage collector, tuning and related errors (watch here, in french). Here are some notes.

Garbage Collector

The classic garbage collector (included into the standard HotSpot JVM) will clean the Young Gen in minor GCs, and the entire heap (including both Young and Tenured gen) during a full GC, which occurs less frequently than the former.

Read https://stackoverflow.com/a/2129294 for some additional information:

Java uses generational garbage collection. This means that if you have an object foo (which is an instance of some class), the more garbage collection events it survives (if there are still references to it), the further it gets promoted. It starts in the young generation (which itself is divided into multiple spaces - Eden and Survivor) and would eventually end up in the tenured generation if it survived long enough.

There is another garbage collector called G1GC which was introduced in Java 6, using a different strategy. Read here for mode details.

Tuning the GC

  1. Activate GC logs. It has minimal overhead. https://stackoverflow.com/a/15319823

    • JRE 8: -XX:+PrintGCDetails -XX:+PringGCDateStamps -Xloggc:gc.log
    • JRE 9: -Xlog:gc*.file="gc.log":uptime
    • JRE 9 also has the ability to turn on GC logs while running:
      • jcmd <pid> VM.log output=file="gc.log" what="gc=debug" decorators="time,level"
      • Get the <pid> via jps or jcmd (JRE8)
  2. Use GCViewer or any other log viewers. A good aim is 95% throughput.

  3. Get info on the heap and GC: jstat -gcutil <pid>

  4. Get object histogram on heap

    • jmap -histo <pid>
    • JDK 8: jcmd <pid> GC.class_histogram
    • JDK 9: jhsdb jmap --histo --pid=<pid>
  5. Get a heap dump

    • jmap -dump:live,format=b,file=<filename.hprof> <pid>
    • JDK 8: jcmd <pid> GC.heap_dump <filename.hprof>
    • JDK 9: jshdb jmap --binaryheap --dumpfile=<filename.hprof> --pid=<pid>
    • Also to generate heap dump on error
      • -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<path to dump>`date`.hprof
  6. Read heap dump with Memory Analyzer Tool (MAT), jOverflow, VisualVM, YourKit, jProfiler

  7. If using G1, use String dedupe

    • -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics
    • JDK 9: Activated by default, deactivate with -XX:-CompactStrings

Warnings & Errors

  1. Off heap OutOfMemoryError (PermGen Space, Metaspace)

    • Increase memory size with -XX:PermSpace / MaxPermSize / MetaspaceSize / MaxMetaspaceSize
    • Investigate with -XX:+TraceClassLoading -XX:+TraceClassUnloading
      • JDK 7: jmap -permstat <pid>
      • JDK 8+: jmap -clstats <pid>
  2. Thread OutOfMemoryError (unable to create new native Thread)

    • A thread in the JVM maps to a thread in the OS
    • Reduce -Xss<max> (thread stack size)
    • Increase number of threads from OS: unlimit -u <max>
  3. Java HotSpot warning: CodeCache is full. Compiler has been disabled

    • -XX:ReservedCodeCacheSize=<max>
  4. Direct Buffer Memory OutOfMemoryError

    • -XX:MaxDirectMemorySize=<max>
  5. Memory used by the JVM itself (native memory)

    • Enable memory tracking -XX:NativeMemoryTracking=summary -XX:NativeMemoryTracking=detail
    • jcmd <pid> VM.native_memory