Java 22中三种垃圾回收GC性能获得了大提升

💡 原文中文,约3000字,阅读约需8分钟。
📝

内容提要

Java 22中的垃圾回收器GC性能有所提升,包括G1区域固定、并行GC的工作分配优化、串行GC的卡片扫描代码优化、G1的区域回收和取消使用GCLocker等改进。此外,还有堆大小调整的改动、代码根集的多线程处理和Loom移除代码缓存清扫器等优化。

🔎

延伸解读

并行GC工作分配优化:解决大对象扫描瓶颈

并行GC在卡片扫描时,旧机制下单个线程可能需独自处理整个大型对象数组,导致反向线程缩放和长暂停。JDK 22通过将大对象数组分割到不同分区,允许多线程并行扫描,并仅处理标记为脏的部分,避免了无效查看。同时,块偏移表采用指数后跳编码,减少查找对象起点的内存访问。这些改动直接提升了并行GC的暂停时间表现。

G1区域固定与GCLocker取消:JNI交互不再阻塞GC

G1在JDK 22中实现了区域固定(JEP 423),当JNI临界区访问数组时,不再完全禁止GC,而是将相关区域标记为固定,允许回收其他区域。同时,G1取消使用GCLocker,Java线程不会因JNI代码而停滞。此外,G1现在能回收疏散失败的区域,避免旧版本被失败区域淹没,提高了恢复能力。这些改进显著增强了G1在混合JNI场景下的可用性。

堆大小调整更一致:减少Eden区域依赖

G1在Remark暂停期间的堆大小调整逻辑得到修改,现在根据-XX:Min/MaxHeapFreeRatio计算变化,不再考虑Eden区域。此前,调整结果高度依赖Remark暂停发生时的Eden占用,导致堆大小变化不确定且可能过于激进。新行为使堆大小调整更具确定性,通常也更温和,有助于减少不必要的GC波动。

Loom移除代码缓存清扫器:暂停时间反而改善

为支持Loom,JDK 22移除了代码缓存清扫器,其工作被转移到STW暂停中。由于清扫器部分组件具有O(n^2)复杂度,移除后大量卸载编译代码时暂停时间曾出现倒退。但通过JDK-8317809等修复,现在暂停时卸载类的速度实际上比移除清扫器前更快。这表明相关优化成功抵消了移除清扫器带来的潜在负面影响。

❓

Q&A

Java 22中垃圾回收器GC性能提升的主要改进是什么?

Java 22中主要改进包括G1区域固定、并行GC工作分配优化和串行GC卡片扫描代码优化。

G1收集器在Java 22中有哪些新功能?

G1收集器现在能回收疏散失败的区域,并取消了对GCLocker的使用,允许在JNI交互时进行垃圾收集。

Java 22中并行GC的工作分配机制有什么变化?

并行GC的工作分配机制现在将堆划分为64kB小块,多个线程可以同时处理这些块,提高了性能。

串行GC在Java 22中有哪些优化?

串行GC的卡片扫描代码得到了优化,减少了年轻卡的收集时间,提升了整体性能。

Java 22中堆大小调整的改动是什么?

堆大小调整变得更加一致,减少了对Eden区域的依赖,使得堆大小变化更具确定性。

Loom移除代码缓存清扫器对垃圾收集有什么影响?

移除代码缓存清扫器后,暂停时间有所改善,卸载类的速度比之前更快。

🏷️

标签

➡️

继续阅读