Week 10 - The Generational Hypothesis and the Modern GCs¶
Conceptual Core¶
"Most objects die young." This is the weak generational hypothesis, and it is what every modern GC except non-generational ZGC (deprecated as default in 23+) and Epsilon is built on. You need to know the family tree: Serial → Parallel → CMS (removed) → G1 → ZGC → Shenandoah → Generational ZGC.
Mechanical Detail¶
- Serial GC (
-XX:+UseSerialGC) - single-threaded; only for tiny heaps / containers. Default in some container configs. - Parallel GC (
-XX:+UseParallelGC) - throughput-optimized, stop-the-world. Default before 9. - G1 GC (
-XX:+UseG1GC, default since 9) - region-based, mostly-concurrent, predictable pause-time goal (-XX:MaxGCPauseMillis=200default). The general-purpose default. - ZGC (
-XX:+UseZGC) - concurrent, region-based, colored pointers, sub-millisecond pauses. Generational ZGC (JEP 439, GA in 21) is the modern form; on 23+ it's the default flavor of-XX:+UseZGC. Use for latency-sensitive services with multi-GB heaps. - Shenandoah (Red Hat,
-XX:+UseShenandoahGC) - concurrent compaction via Brooks pointers / load-reference barriers. Comparable use case to ZGC. - Epsilon (
-XX:+UseEpsilonGC) - no-op collector. For short-lived batch jobs or GC-perf testing. - Picking: G1 by default; ZGC for latency-sensitive ≥4GB heaps; Parallel for throughput-only batch; Serial for tiny containers; Shenandoah if your stack is RHEL-flavored and you've measured it wins.
Lab¶
Take a sample allocation-heavy app (a small JSON parser benchmark works). Run it under all four major GCs with identical heap. Collect logs with -Xlog:gc*=info:file=gc.log:time,uptime. Plot pause times.
Idiomatic Drill¶
Read JEPs 439 (Generational ZGC) and 248 (Make G1 the Default).
Production Hardening Slice¶
Add a GC-log parser to your hardening/ template (or wire up gceasy.io / GCViewer). One command from gc.log to a chart.