Performance & Optimization

GC Tuning & Logging

GC tuning starts with GC logs — free, always-on-able, and containing allocation rates, pause causes, and promotion behavior. Size the heap, pick the collector, set a pause goal; everything further needs log evidence.
  • Always run with -Xlog:gc*:file=gc.log:time,uptime,level,tags — negligible overhead, priceless data
  • First-order knobs: heap size (-Xmx/-Xms), collector choice, -XX:MaxGCPauseMillis (G1)
  • Read for: allocation rate (MB/s), pause durations & causes, promotion rate, full-GC frequency
  • Set -Xms = -Xmx in servers/containers — resizing causes pauses and confuses ergonomics
  • Symptom→cause: frequent young GC = high allocation; growing old gen = leak or premature promotion; "to-space exhausted" (G1) = evacuation pressure
  • Analyze with GCViewer / gceasy.io; correlate pauses with request-latency spikes
Unified logging (Java 9+) and what a line means
$ java -Xlog:gc*:file=gc.log:time,uptime:filecount=5,filesize=20m -jar app.jar

[2026-07-07T12:00:01.234+0000][12.345s] GC(42) Pause Young (Normal) (G1 Evacuation Pause)
      Eden: 512M(512M)->0B(480M) Survivors: 32M->48M Heap: 1200M(2048M)->720M(2048M) 14.2ms
// eden filled (512M since last young GC) → allocation rate ≈ 512M / interval
// heap after: 720M live-ish → old-gen occupancy trend = leak detector

The tuning loop (Optimizing Java ch. 8): confirm GC is actually the problem (correlate pause log timestamps with latency spikes — if p99 spikes without pauses, look elsewhere); compute allocation rate and promotion rate from the logs; then address the dominant term. High allocation → reduce garbage creation in hot paths (Language Performance) or grow eden. High promotion → objects living just long enough to promote; investigate mid-lived caches and batch sizes. Full GCs recurring → undersized heap or a leak (heap-dump time).

Symptoms → first moves
Log symptomLikely causeFirst move
Young pauses too frequenthigh allocation ratereduce allocation; bigger young gen
Young pauses too longtoo much surviving datacheck survivor overflow, object lifetimes
Mixed/old collections struggling (G1)old gen filling with live databigger heap; find the retention
to-space exhausted / evacuation failureno room to evacuateincrease heap/reserve, lower IHOP
Recurring Full GCleak, undersized heap, or System.gc()heap dump; -XX:+DisableExplicitGC
Humongous allocations (G1)objects > 50% region sizechunk big arrays; larger G1HeapRegionSize
Sources
  • Optimizing JavaCh. 8 — GC Logging, Monitoring, Tuning, and Tools
  • Optimizing Cloud Native Java (2nd ed.)Ch. 4–5 — Garbage Collection
  • Java Secrets: High Performance and ScalabilityPerformance tuning chapters