The full picture
| Collector | Design goal | Pause profile | Pick when |
|---|---|---|---|
| Serial | Smallest footprint | Long, single-threaded | Tiny containers, CLI tools |
| Parallel | Max throughput | Long but efficient STW | Batch/ETL where p99 latency is irrelevant |
| G1 (default) | Balanced, region-based | Target via MaxGCPauseMillis (~200ms default) | Most services, heaps 4–32GB |
| ZGC (generational) | Ultra-low latency, concurrent | <1ms typical, heap-size independent | Trading, gateways, multi-100GB heaps |
| Shenandoah | Low latency (Red Hat lineage) | Few ms, concurrent compaction | Similar niche to ZGC |
A sane tuning workflow: (1) fix the heap size — in containers via MaxRAMPercentage; (2) pick the collector by SLO; (3) enable -Xlog:gc* and observe allocation rate, promotion rate, pause distribution; (4) only then touch advanced flags. 90% of 'GC problems' are actually allocation-rate problems or heap-sized-too-small problems — fixing the code (object churn, caching giant graphs) beats flag alchemy.