Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News Java Enhances Z Garbage Collector with Generational Capabilities

Java Enhances Z Garbage Collector with Generational Capabilities

JEP 439, Generational ZGC, has been promoted from Targeted to Completed for JDK 21. This JEP proposes to improve application performance by extending the Z Garbage Collector (ZGC) to maintain separate generations for young and old objects. This will allow ZGC to collect young objects, which tend to die young, more frequently.

The Z Garbage Collector, available for production use since JDK 15, is designed for low latency and high scalability. It performs the majority of its work while application threads are running, pausing those threads only briefly. ZGC's pause times are consistently measured in microseconds, making it a preferred choice for workloads that require low latency and high scalability.

The new generational ZGC aims to lower the risks of allocation stalls, reduce the required heap memory overhead, and decrease garbage collection CPU overhead. These benefits are expected to come without a significant reduction in throughput compared to non-generational ZGC. The essential properties of non-generational ZGC, such as pause times not exceeding one millisecond and support for heap sizes from a few hundred megabytes up to many terabytes, will be preserved.

The generational ZGC is based on the weak generational hypothesis, which states that young objects tend to die young while old objects tend to stick around. By collecting young objects more frequently, ZGC can improve the performance of applications.

Generational ZGC will initially be available alongside non-generational ZGC. Users can select Generational ZGC by adding the -XX:+ZGenerational option to the -XX:+UseZGC command-line option. Generational ZGC will become the default in future releases, and eventually, non-generational ZGC will be removed.

$ java -XX:+UseZGC -XX:+ZGenerational ...

The new generational ZGC splits the heap into two logical generations: the young generation for recently allocated objects and the old generation for long-lived objects. Each generation is collected independently of the other, allowing ZGC to focus on collecting the profitable young objects.

Generational ZGC introduces several design concepts that distinguish it from non-generational ZGC and other garbage collectors. These include no multi-mapped memory, optimized barriers, double-buffered remembered sets, relocations without additional heap memory, dense heap regions, large objects, and full garbage collections.

The introduction of Generational ZGC is a significant step forward in improving the performance of applications running on the Java platform. By focusing on collecting young objects more frequently, Generational ZGC can provide lower latency, reduced memory overhead, and improved CPU utilization, making it a better solution for most use cases than non-generational ZGC.

It introduces a more complex system that uses explicit code in load and store barriers and concurrently runs two garbage collectors. The new system eliminates the use of multi-mapped memory, making it easier for users to measure heap memory usage and potentially increasing the maximum heap size beyond the 16-terabyte limit of non-generational ZGC. The load and store barriers are optimized using techniques such as fast paths and slow paths, remembered-set barriers, SATB marking barriers, fused store barrier checks, and store barrier buffers.

Generational ZGC also introduces double-buffered remembered sets for precise tracking of inter-generational pointers and allows relocations without additional heap memory, thus enabling efficient young generation collection. The system also handles large objects well, allowing them to be allocated to the young generation and promoting them to the old generation if they are long-lived. The full garbage collections consider pointers from objects in the young generation to objects in the old generation as roots of the old-generation object graph.

In conclusion, the implementation of Generational ZGC in OpenJDK introduces a more complex system, running two garbage collectors concurrently and utilizing more intricate barriers and coloured pointers. Despite the complexity, the long-term goal is to fully replace the non-generational ZGC with the generational version to minimize maintenance costs. While most use cases are expected to benefit from Generational ZGC, some non-generational workloads might experience slight performance degradation. However, the potential overhead is believed to be offset by the benefits of not having to collect objects in the old generation frequently.

Future improvements and optimizations of Generational ZGC will be driven by benchmarks and user feedback. The introduction of Generational ZGC is a significant step forward in improving the performance of applications running on the Java platform.

About the Author

Rate this Article