Flags
-XX:+UseZGC selects the Z Garbage Collector. ZGC performs most GC work
concurrently with application threads, making it attractive for services with strict tail
latency goals and larger heaps.
Flag details
- -XX:+UseZGC
- Selects ZGC, a scalable low-latency collector. In Java 25, ZGC uses generational behavior by default, so young objects can be collected more efficiently than old long-lived objects.
- -Xmx8g
- Gives ZGC a maximum heap budget. ZGC needs enough free space to collect concurrently while the application keeps allocating.
- -XX:+AlwaysPreTouch
- Touches heap pages at startup so physical memory is committed early. This can make latency more predictable after startup, but increases startup time and commits memory immediately.
- -Xlog:gc*
- Shows ZGC cycles, allocation stalls, heap capacity changes, relocation activity, and whether concurrent collection is keeping up.
How ZGC works
ZGC is designed to keep GC pauses very short by doing marking, relocation, and reference processing work concurrently with application threads. It uses load barriers so application code can safely access objects while the collector is moving them.
Generational ZGC separates young and old objects. Since most objects die young, collecting the young generation more often reduces CPU and memory pressure compared with treating the whole heap uniformly. ZGC still needs CPU headroom; if allocation outruns concurrent collection, the application can see allocation stalls.
When to use it
Use this for latency-sensitive APIs, trading platforms, real-time-ish request processing, and services where occasional long G1 pauses are unacceptable. Give ZGC enough CPU and heap headroom so concurrent collection can keep up with allocation.
-XX:+UseZGC, heap limits, and logs.Java version support
ZGC arrived as an experimental collector in Java 11 and became production-ready in Java 15.
Generational ZGC arrived in Java 21, became the default ZGC mode in Java 23, and the old
non-generational mode was removed in Java 24. On Java 25, -XX:+UseZGC means
generational ZGC.
Related JEPs
- JEP 333 - ZGC experimental, delivered in JDK 11.
- JEP 351 - ZGC uncommits unused memory, delivered in JDK 13.
- JEP 364 - ZGC on macOS, delivered in JDK 14.
- JEP 365 - ZGC on Windows, delivered in JDK 14.
- JEP 376 - ZGC concurrent thread-stack processing, delivered in JDK 16.
- JEP 377 - ZGC production, delivered in JDK 15.
- JEP 439 - Generational ZGC, delivered in JDK 21.
- JEP 474 - Generational ZGC by default, delivered in JDK 23.
- JEP 490 - Remove non-generational ZGC mode, delivered in JDK 24.
Examples
java -XX:+UseZGC -Xmx8g \
-Xlog:gc*:file=logs/zgc.log:time,uptime,level,tags \
-jar latency-api.jar
Use this as the first ZGC production experiment: one collector flag, heap limit, and logs.
java -XX:+UseZGC -Xms4g -Xmx4g \
-XX:+AlwaysPreTouch \
-jar latency-api.jar
Use this when startup can be slower but you want heap pages committed before traffic arrives.
Verify
Look for allocation stalls, GC cycle frequency, CPU saturation, and request tail latency under realistic load.