Understanding ZGC: Low‑Latency Garbage Collection in Java
ZGC (Z Garbage Collector) is a scalable, low‑latency collector introduced in JDK 11, featuring sub‑millisecond pause times, region‑based memory layout, colored pointers, NUMA awareness, and concurrent phases, with detailed explanations of its architecture, parameters, triggers, and log analysis.
ZGC Overview
Z Garbage Collector (ZGC) is a scalable low‑latency garbage collector introduced in JDK 11 and stabilized in JDK 15. Its design goals are:
<1 ms maximum pause time (JDK < 16: 10 ms, JDK ≥ 16: <1 ms).
Pause time does not increase with heap, live‑set, or root‑set size.
Supports heap sizes from 8 MB up to 16 TB.
Key characteristics of ZGC include concurrency, region‑based layout, compression, NUMA awareness, colored pointers, and load barriers.
Core Architecture
ZGC performs the heavy work concurrently while Java threads continue running, greatly limiting GC impact on application response time.
ZGC Features
ZGC is a region‑based, (temporarily) non‑generational collector that uses read barriers, colored pointers, and multi‑mapping to implement a concurrent mark‑compact algorithm focused on low latency.
Memory Layout
ZGC does not use generations. It adopts a region‑based heap where regions are dynamic in size and can be created or destroyed as needed. On x64 platforms, regions come in three sizes:
Small Region (2 MiB) – stores objects smaller than 256 KiB.
Medium Region (32 MiB) – stores objects from 256 KiB up to 4 MiB.
Large Region – size is a multiple of 2 MiB and holds objects 4 MiB or larger.
NUMA Awareness
NUMA (Non‑Uniform Memory Access) provides each CPU with a local memory region, reducing contention and improving performance. ZGC automatically detects and fully utilizes NUMA architectures, which is especially beneficial for large‑scale systems.
Colored Pointer
Colored pointers store GC metadata directly in object references instead of object headers. Each 64‑bit reference is divided as follows:
18 bits reserved for future use.
1 bit Finalizable flag.
1 bit Remapped flag.
1 bit Marked1 flag.
1 bit Marked0 flag.
42 bits object address (supporting up to 4 TB of memory).
Two mark bits allow alternating between GC cycles, invalidating the previous cycle’s marks.
Advantages of Colored Pointers
When all live objects in a region are moved, the region can be released immediately because the forward table records old‑to‑new address mappings.
Self‑healing capability reduces the need for write barriers; a single read barrier suffices.
Future extensibility: 18 unused bits leave room for additional features.
Multi‑Mapping Addressing
ZGC uses multi‑mapping on Linux to map several virtual addresses to the same physical memory, allowing the colored pointer’s flag bits to act as address segment selectors. This technique expands the effective address space without additional hardware support.
Read Barrier
ZGC employs read barriers to correct references when objects are relocated. If a thread accesses an object that has been moved, the barrier reads the Remapped flag, redirects the reference to the new location, and updates the pointer.
<code>Object o = obj.fieldA; // Loading an object reference from heap
<load barrier needed here>
Object p = o; // No barrier, not a load from heap
o.doSomething(); // No barrier, not a load from heap
int i = obj.fieldB; // No barrier, not an object reference
</code>Read barriers add roughly 4 % overhead to throughput.
ZGC Work Process
ZGC operates in four concurrent phases:
Concurrent Mark : Traverses the object graph, marking reachability using the colored pointer bits.
Concurrent Prepare for Relocate : Determines the set of regions (Relocation Set) that will be evacuated.
Concurrent Relocate : Copies live objects to new regions, maintains a forward table, and uses memory barriers to self‑heal stale references.
Concurrent Remap : Fixes remaining references to old locations; this work is merged into the next marking phase to avoid an extra full‑heap scan.
Core Parameters
-XX:+UseZGC– Enable ZGC.
-Xmx– Set maximum heap size.
-Xlog:gc– Enable GC logging.
-Xlog:gc*– Enable detailed GC logging.
GC Trigger Conditions
Timed trigger : Configurable via
ZCollectionInterval.
Warm‑up trigger : Fires when heap usage reaches 10 %, 20 %, or 30 %.
Allocation rate : Predicts when the heap will be exhausted based on recent allocation speed.
Proactive trigger : Fires after a 10 % heap growth or 5 minutes without GC, whichever comes first.
Metadata allocation : Triggers when the metadata space is insufficient.
Explicit trigger : Invocation of
System.gc().
Allocation stall : Occurs when allocation requests block because the heap is full.
GC Log Analysis Example
An example program that continuously allocates 2 KB byte arrays is run with
-XX:+UseZGC -Xmx8m -Xlog:gc*. The log shows phases such as “Start”, “Phase‑Pause Mark Start/End”, “Phase‑Pause Relocate Start”, heap size changes, and statistical summaries that help identify allocation stalls or excessive pause times.
Conclusion
The article describes ZGC’s concepts, features, and operation.
Most production environments still use JDK 8/11 with
ParNew+CMSor
G1, but ZGC offers a modern low‑latency alternative.
Java developers should stay informed about new runtime technologies to remain competitive.
References
Deep Understanding of the JVM, 3rd edition, Zhou Zhimin.
https://wiki.openjdk.java.net/display/zgc/Main
http://cr.openjdk.java.net/~pliden/slides/ZGC-Jfokus-2018.pdf
https://tech.meituan.com/2020/08/06/new-zgc-practice-in-meituan.html
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.