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=-Xmxin 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
$ 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 detectorThe 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).
| Log symptom | Likely cause | First move |
|---|---|---|
| Young pauses too frequent | high allocation rate | reduce allocation; bigger young gen |
| Young pauses too long | too much surviving data | check survivor overflow, object lifetimes |
| Mixed/old collections struggling (G1) | old gen filling with live data | bigger heap; find the retention |
to-space exhausted / evacuation failure | no room to evacuate | increase heap/reserve, lower IHOP |
| Recurring Full GC | leak, undersized heap, or System.gc() | heap dump; -XX:+DisableExplicitGC |
| Humongous allocations (G1) | objects > 50% region size | chunk big arrays; larger G1HeapRegionSize |