Hard java java-21

How do G1 and ZGC compare?

The 30 second answer

G1, the default, splits the heap into regions and tries to meet a pause-time goal, two hundred milliseconds by default, while keeping good throughput. ZGC does almost all its work while the application runs, so pauses stay very short even on huge heaps, at the cost of some CPU and memory overhead. I'd keep G1 for general services and pick ZGC when tail latency really matters.

G1ZGC
Defaultyesno, -XX:+UseZGC
Heap layoutequal-sized regions, young and oldregions of varying sizes; generational in 21 with a flag
Pausestargets -XX:MaxGCPauseMillis (default 200 ms)very short and mostly independent of heap size
Compactionduring evacuation pausesconcurrent
Best formost serviceslarge heaps, strict latency

Tuning: for G1, set the heap size and the pause goal, and avoid fixing the young-generation size, which overrides the pause-time logic. For ZGC, the most important setting is the max heap size (-Xmx), so the collector has enough headroom for the allocation rate.

[Opinion] ZGC usually costs some throughput and memory compared with G1. Measure p99 latency and CPU on your own workload before switching.

On Java 21 use -XX:+UseZGC -XX:+ZGenerational for generational ZGC (JEP 439); from Java 23 it is the default ZGC mode.

Sources: GC Tuning Guide: G1, GC Tuning Guide: ZGC, JEP 439: Generational ZGC

Sources (0)
See inline citations in the answer above.