分代ZGC早期访问构建版本发布


经过对 Generational(分代/世代) ZGC 的大量努力,第一个 Early Access 版本已在 jdk.java.net/genzgc 上发布并可供测试。

分代ZGC具有更高分配率和更大活动对象集的 Java 程序尤其更有可能通过使用 ZGC 获得持续的延迟优势:

  • Java 线程分配停止的风险更小
  • 降低 Java 堆内存开销
  • 降低 CPU 使用率
  • 显着提高持续对象分配率

传统ZGC 是将年轻对象(新分配的对象)和老对象(最近一次 GC 期间未删除的对象)存储在一起,迫使它同时收集所有对象。旧对象往往会留下来,收集它们通常需要更多资源并产生更少的内存。

分代 ZGC 改变了 ZGC 在 Java 堆中存储对象的方式。新旧对象存储在 Java 堆的不同区域,即所谓的分代。
分代使 ZGC 能够单独收集相应的年轻对象。这允许 Generational ZGC 使用相当少的资源(CPU 和内存)来运行,从而能够解决更多 Java 工作负载的 GC 延迟问题。

使用分代ZGC时,某些 Java 工作负载甚至可能会遇到吞吐量增加(由于资源使用率低得多)。例如:运行Apache Cassandra时基准测试中,Generational ZGC 设法以堆大小的四分之一运行,并且与非分代 ZGC 相比,仍然获得四倍的吞吐量(同时仍然没有超过 1 毫秒的暂停时间)。

分代 ZGC 将堆分成两个逻辑代:一个用于新分配的对象,即年轻代,另一个用于长期存在的对象,即老年代。每一代都是独立收集的,所有垃圾收集都是在 Java 应用程序运行时同时进行的。只有极少量的 ZGC 工作需要暂停 Java 应用程序的线程,然后只暂停很短的时间(不到一毫秒)。

通过并发垃圾回收,GC 的线程与 Java 应用程序的线程同时读取和修改 Java 对象图。为了避免破坏堆并为 Java 应用程序提供对象图的一致视图,所有线程都需要协作。ZGC 通过使用彩色指针、加载屏障和存储屏障来处理这种协作。