Java 通过分代功能增强 Z 垃圾收集器
2023年07月06日 由 Susan 发表
350829
0
JEP 439, 分代ZGC,已经从目标状态提升为完成状态,将包含在JDK 21中。该JEP的提议是通过扩展Z Garbage Collector (ZGC) 来提高应用程序性能,使其能够为年轻群体和老年群体服务,维护不同的分代。这将使ZGC能够更频繁地回收对象群体,因为这些对象往往寿命较短。
Z Garbage Collector自JDK 15以来已经可用于生产环境,它专为低延迟和高可伸缩性而设计。它会在应用程序线程运行时执行大部分工作,仅短暂暂停这些线程。ZGC的暂停时间通常以微秒为单位,使其成为需要低延迟和高可伸缩性的工作负载的首选。
新的分代ZGC旨在降低分配停顿的风险,减少所需的堆内存开销,并降低垃圾收集的CPU开销。与非分代ZGC相比,这些优势预计不会显著降低吞吐量。非分代ZGC的基本特性,如暂停时间不超过一毫秒和对从几百兆字节到数太字节的堆大小的支持,将被保留。
分代ZGC基于弱分代假设,该假设认为年轻对象往往寿命较短,而老年对象会长时间存在。通过更频繁地回收年轻对象,ZGC能够提高应用程序的性能。
初始阶段,分代ZGC将与非分代ZGC并存。用户可以通过将-XX:+ZGenerational选项添加到-XX:+UseZGC命令行选项来选择使用分代ZGC。在未来的版本中,分代ZGC将成为默认选项,最终非分代ZGC将被移除。
$ java -XX:+UseZGC -XX:+ZGenerational ...
新的分代ZGC将堆分为两个逻辑分代:年轻代用于最近分配的对象,老年代用于长寿命对象。每个分代都独立进行垃圾回收,使ZGC能够专注于收集有利可图的年轻对象。
分代ZGC引入了几个与非分代ZGC和其他垃圾收集器不同的设计概念。其中包括无多映射内存、优化的屏障、双缓冲的记忆集、无需额外堆内存的重定位、密集堆区域、大对象和完全垃圾回收。
引入分代ZGC是改进在Java平台上运行应用程序性能的重要一步。通过更频繁地收集年轻对象,分代ZGC能够提供更低的延迟、减少的内存开销和改善的CPU利用率,使其成为大多数使用场景下比非分代ZGC更好的解决方案。
分代ZGC引入了更复杂的系统,使用显式代码在加载和存储屏障中,并同时运行两个垃圾收集器。新系统消除了多映射内存的使用,使用户更容易测量堆内存使用量,并可能将最大堆大小超出非分代ZGC的16太字节限制。加载和存储屏障使用了快速路径和慢速路径、记忆集屏障、SATB标记屏障、融合存储屏障检查和存储屏障缓冲区等技术进行优化。分代ZGC还引入了双缓冲的记忆集,可以精确跟踪分代间指针,并允许无需额外堆内存的重定位,从而实现高效的年轻代回收。该系统还能很好地处理大对象,允许将它们分配给年轻代,并将其提升到老年代,如果它们具有长寿命。完全垃圾回收会将年轻代对象对老年代对象的指针作为老年代对象图的根进行处理。
总之,在OpenJDK中实现分代ZGC引入了更复杂的系统,同时运行两个垃圾收集器,并利用更复杂的屏障和彩色指针。尽管复杂性增加,长期目标是完全替换非分代ZGC,以降低维护成本。尽管大多数使用场景预计将受益于分代ZGC,但某些非分代工作负载可能会出现轻微的性能下降。然而,由于无需频繁收集老年代对象而带来的好处,潜在的开销被认为是可以抵消的。未来对分代ZGC的改进和优化将受基准测试和用户反馈的驱动。引入分代ZGC是改善在Java平台上运行应用程序性能的重要一步。
来源:https://www.infoq.com/news/2023/07/java-enhance-zgc/