On this page
GC Tuning
Garbage collector tuning selects the right GC algorithm and configures it for your application’s latency and throughput requirements.
GC Algorithms
| Collector | Flag | Best for | Pause time |
|---|---|---|---|
| G1 (default Java 9+) | -XX:+UseG1GC |
General purpose, balanced | Low–moderate |
| ZGC | -XX:+UseZGC |
Large heaps, low latency | <1ms |
| Shenandoah | -XX:+UseShenandoahGC |
Low latency, concurrent | <10ms |
| Parallel | -XX:+UseParallelGC |
Throughput, batch jobs | Moderate |
| Serial | -XX:+UseSerialGC |
Small apps, single core | High |
G1 GC Configuration
Default since Java 9. Good starting point for most applications:
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200 # target max pause
-XX:G1HeapRegionSize=16m # region size (auto by default)
-XX:InitiatingHeapOccupancyPercent=45 # start concurrent marking
-XX:G1ReservePercent=10
ZGC (Java 15+ production-ready)
For applications requiring sub-millisecond pauses:
-XX:+UseZGC
-Xmx16g
# ZGC works best with larger heaps (8g+)
Characteristics:
- Pauses typically <1ms regardless of heap size
- Concurrent compaction
- No stop-the-world for most phases
GC Logging
# Java 9+ unified logging
-Xlog:gc*:file=/var/log/gc.log:time,uptime,level,tags:filecount=5,filesize=20m
# Key log events
# Pause Young (Normal) — minor GC
# Pause Full — major GC (bad, investigate)
# Concurrent Cycle — G1 concurrent marking
Reading GC Logs
[2024-01-15T10:30:00.123+0000] GC(42) Pause Young (Normal) 512M->128M(2048M) 15.234ms
| Field | Meaning |
|---|---|
| GC(42) | GC cycle number |
| Pause Young | Minor GC in young generation |
| 512M->128M | Heap before → after |
| (2048M) | Current heap capacity |
| 15.234ms | Pause duration |
Warning signs:
- Frequent Full GC → heap too small or memory leak
- Pause times exceeding target → tune or switch collector
Allocation Failure→ heap pressure
Choosing a Collector
Latency-sensitive (APIs, trading)?
└─ Yes → ZGC or Shenandoah (heap > 4g)
└─ No → Throughput priority?
└─ Yes → Parallel GC
└─ No → G1 GC (default, good balance)
Tuning Workflow
- Baseline — run with defaults, enable GC logging
- Measure — collect pause times, throughput under load
- Identify — frequent Full GC? Long pauses? High allocation rate?
- Adjust — heap size, collector, specific flags
- Validate — re-test under production-like load
jstat Monitoring
# GC utilization summary every 2 seconds
jstat -gcutil <pid> 2000
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 45.23 67.89 32.10 95.12 91.30 142 1.234 3 0.456 1.690
# O (Old gen) consistently > 85% → increase heap or tune
# FGC growing rapidly → memory leak or undersized old gen
Best Practices
- Start with G1 defaults — only tune when metrics show problems
- Use ZGC for latency-critical services with heaps > 4GB
- Always enable GC logging in production
- Set
MaxGCPauseMillisas a target, not a guarantee - Never disable GC (
-Xnoclassgcetc.) without expert knowledge