Skip to content

Enabling GC Logging

GC logging is cheap (typically < 3% overhead) and is your best friend when a production incident strikes. Enable it always, everywhere.

Java 9 and later (unified logging)

bash
java -Xlog:gc*:file=/var/log/myapp/gc.log:time,uptime,level,tags:filecount=5,filesize=20m -jar app.jar
  • -Xlog:gc* — everything GC related, including heap sizes and pause phases (required for a complete EasyGC report).
  • file=... — rotate instead of growing forever (filecount / filesize).
  • time,uptime — wall-clock and JVM-uptime stamps on every line.

Minimum useful set

-Xlog:gc:file=gc.log already works, but -Xlog:gc* gives the full picture (region stats, metaspace, phase timings).

Java 8 and earlier

bash
java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime \
     -Xloggc:/var/log/myapp/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 \
     -XX:GCLogFileSize=20M -jar app.jar
  • -XX:+PrintGCDetails — per-generation sizes (young/old/metaspace) — required for the memory breakdown.
  • -XX:+PrintGCDateStamps — wall-clock timestamps for correlating with application logs.
  • On Java 8u92+ you can also add -XX:+PrintGCTimeStamps for uptime stamps.

What a good log looks like

Java 9+ (G1):

[2024-05-01T10:00:00.524+0000][0.524s][info][gc] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 412M->34M(1024M) 12.134ms

Java 8 (Parallel):

2024-05-01T10:00:01.234+0000: 1.234: [GC (Allocation Failure) [PSYoungGen: 262144K->32768K(305664K)] 262144K->49152K(1007616K), 0.0383211 secs] [Times: user=0.12 sys=0.03, real=0.04 secs]

Both carry everything EasyGC needs: when the collection happened, why it was triggered, heap before → after, capacity and how long the JVM was stopped.

Container notes

  • Write the log to a mounted volume, not the container filesystem.
  • Remember that the JVM sees container memory limits — check -XX:MaxRAMPercentage too.