Java GC Type
The Z Garbage Collector (ZGC) is a scalable low latency garbage collector. ZGC performs all expensive work concurrently, without stopping the execution of application threads for more than a millisecond. It is suitable for applications which require low latency. Pause times are independent of the heap size that is being used. ZGC works well with heap sizes from a few hundred megabytes to 16TB.
ZGC was initially introduced as an experimental feature in JDK 11, and was declared Production Ready in JDK 15. In JDK 21 was reimplemented to support generations.
ZGC usage
At its core, ZGC is a concurrent garbage collector, meaning all heavy lifting work is done while Java threads continue to execute. This greatly limits the impact garbage collection will have on your application’s response time. ZGC is a scalable low-latency garbage collector capable of handling heaps ranging from 8MB to 16TB in size, with sub-millisecond max pause times.
ZGC’s low latency and ability to scale to handle large live sets would make it a good candidate for web applications. Web applications frequently service many requests simultaneously, often resulting in maintaining larger live sets. Consistent responsiveness also helps with system stability. This pairs well with ZGC’s strengths.
On the other hand, while ZGC can operate with heaps as small as 8 MB, it is strongly discouraged to use ZGC in such a scenario.
Try them out
Start With the default GC, G1
- If the Throughput is insufficient
- try enabling Parallel GC
- If pause times are too long
- try ZGC
ZGC cycle
The ZGC (Z Garbage Collector) performs a few Stop-the-World (STW) pauses, such as Pause Mark Start
, Pause Mark End
, and Pause Relocate Start
.
These pauses are brief, typically under a millisecond, and are necessary to ensure consistency and correctness in the garbage collection process. Here’s why these pauses occur.
Pause Name | Purpose | Reason for STW |
---|---|---|
Pause Mark Start | Capture root references | Ensure consistency of the root set before marking starts. |
Pause Mark End | Finalize marking and process references | Ensure all live objects are identified and prepare for relocation. |
Pause Relocate Start | Finalize the relocation set and prepare for object movement | Ensure consistency before relocating objects. |
Colored Pointers
Colored pointers in ZGC are just normal pointers with extra information embedded in them.
This extra information helps ZGC track and manage objects during concurrent garbage collection without stopping the application.
It improves the efficiency of garbage collection by allowing ZGC to track live objects, move them, and perform other tasks in the background with minimal impact on performance.
- first 16 bits: remain in reserve for future use
-
last 44 bits: object address (16TB address space)
- 4 bits
- Mark Bits: These bits indicate if an object is marked as live or reachable. ZGC uses two alternating bits (
Marked0
andMarked1
) to track this.- If the pointer is colored with a “mark bit” ZGC knows this object is in use.
- Remapped Bit: This bit tells ZGC if the pointer is pointing to an object that has been moved (remapped) during compaction.
- If the pointer is colored with a “remapped bit” ZGC knows the object has been moved and will automatically follow the new memory location.
- Finalizable Bit: This bit indicates if the object is only reachable through a finalizer. Note that finalization was designated as deprecated for removal in JDK 18.
- Mark Bits: These bits indicate if an object is marked as live or reachable. ZGC uses two alternating bits (
Heap Multi-Mapping
Because ZGC can move the physical location of an object in heap memory while the application is running, multiple paths need to be provided to the current physical location where the object resides. In ZGC, this is accomplished through heap multi-mapping. With multi-mapping, the physical location of an object is mapped to three views in virtual memory, corresponding to each of the pointer’s potential “colors”. This allows a load barrier to locate an object if it has been moved since the last synchronization point.
Load Barriers
Why Do We Need a Load Barrier in ZGC?
In ZGC, objects can be moved around in memory during garbage collection (in the compaction phase). If an object is relocated, any reference to it must be updated to point to the new location of the object. Since ZGC performs most of its work concurrently with the application, the load barrier ensures that the program doesn’t accidentally use stale references (outdated memory locations) during this process.
How Does It Work?
- When a program loads a reference to an object (say, via a field access or array access), the load barrier intercepts this access.
- If the object has been moved during garbage collection (i.e., it’s part of the relocation set), the load barrier ensures that the reference is updated to point to the new location of the object.
- This process happens in the background while the application is running, and it ensures that the application always accesses the correct location of the object, even if ZGC has moved it.
Benefits of Load Barriers in ZGC
- No Application Pause: ZGC can move objects and manage memory without needing to stop the application, thanks to the load barrier. The barrier allows the application to continue running while still being safe and consistent.
- Consistency: The load barrier ensures that the program always reads the correct memory location, even when objects are relocated or modified during garbage collection.
- Concurrency: ZGC can do concurrent work, like relocating objects, while the application continues to access them as if nothing changed, making garbage collection less intrusive.
Regions
This follows a similar pattern to G1 GC, which also uses memory regions. However, ZGC regions, internally defined as ZPages, are more dynamic, with small, medium, and large sizes; the number of active regions can increase and decrease depending on the needs of the live set.
Small Regions
- size: 2MB
- Objects less than 1/8th (12.5%) the size of a small region, so less than or equal to 256 KB, are stored in a small region.
Medium Regions
- size: 32MB (if heap bigger than 1GB)
- Objects 1/8th (12.5%) or less in size than the set size of a medium region will be stored there.
Large Regions
- size: tightly fitted in 2 MB increments to the object’s size.
- 13 MB object would be stored in a 14 MB large region.
- Any object too large to fit in a medium region will be placed in its own large region.
vs G1GC
Feature | G1GC | ZGC |
---|---|---|
Primary Goal | Low pauses + good throughput | Ultra-low pauses |
Heap Size | Medium to large (up to ~32 GB+) | Very large (up to 16 TB) |
Pause Times | Predictable but grow with heap size | Always very low (<10 ms) |
Compaction | Stop-the-world or incremental | Fully concurrent |
Throughput | Higher | Slightly lower |
Concurrent Phases | Partial | Mostly concurrent |
reference
- https://wiki.openjdk.org/display/zgc/Main
- https://dev.java/learn/jvm/tool/garbage-collection/zgc-overview/
- https://dev.java/learn/jvm/tool/garbage-collection/zgc-deepdive/
- https://cr.openjdk.org/~pliden/slides/ZGC-PLMeetup-2019.pdf