服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

JDK 20 中垃圾回收的新变化

日期: 来源:ImportNew收集编辑:

(给ImportNew加星标,提高Java技能)


本文总结了 Hotspot 的 STW(Stop The World)垃圾收集器在 JDK 20 版本中的更新和改进。


此版本不包含 GC 的任何 JEP(JDK 增强建议),但是 Generational ZGC 的 JEP 最近已达到 Candidate(候选)状态,因此也许它将为 JDK 21 做好准备 :)


除此之外,JDK 20 的整个 Hotspot GC 子组件总共解决或关闭了约 220 个更改。


并行 GC


并行 GC 唯一显著改进是在 Full GC 过程中处理跨越整理区域的对象的并行化(JDK-8292296)。而非在最后的单线程阶段迭代和修正这些对象,工作者线程会收集跨越它们本地整理区域的对象并自行处理。


M. Gasson 指出在某些情况下全 GC 暂停时间减少了 20%。

讨论链接:https://github.com/openjdk/jdk/pull/10313


串行 GC


串行 GC 没有重大变化,只进行了一些代码清理工作。


G1 GC


下面是 JDK 20 中 G1 GC 的更新列表:


1、JDK-8210708 通过删除遍及整个 Java 堆的一个标记位图,将 G1 本地内存占用量减少约 Java 堆大小的 1.5%。


G1 并发标记的博客包括对该更改的详细讨论。

文章链接:https://tschatzl.github.io/2022/08/04/concurrent-marking.html


该博客的内容让原始 G1 论文 中有关并发标记的信息过时了。现在这篇论文中几乎没有有关当前 G1 的准确信息了。

论文链接:http://cs.williams.edu/~dbarowy/cs334s18/assets/p37-detlefs.pdf


实际上这篇博客的内容某种程度上也过时了:JDK-8295118 把名为“清除声明标记(Clear Claimed Marks)”的从并发启动垃圾回收暂停中移除了,针对这个标记的准备工作偶尔会非常耗时。一个名为“并发清除声明标记(Concurrent Clear Claimed Marks)”的新阶段将在日志中出现,即带有 gc+marking=debug 日志记录。


为了给 G1 的未来区域固定(Region Spinning)支持做准备,JDK-8256265 在处理被用户固定的区域(或者由于 Java 堆中没有空间而无法清理)时,将并行化粒度降低了。现在,任务粒度是部分区域,而不是按线程分配整个区域。这使线程更好地共享工作,大大减少了无效等待完成的时间。


2、JDK-8137022 使精细化线程控制更具自适应性。


以前,在垃圾回收暂停期间 G1 计算了离散阈值,以此来激活和停用特定精细化线程以在 mutator 时间中帮助进行精细化。这个计算是基于用户希望在垃圾回收暂停期间花费在精细化卡片上的允许时间(选项 XX:G1RSetUpdatingPauseTimePercent)、最近的下一个暂停的间隔以及很多“魔法”。


编注:“堆被划分为一组 card 卡片,每个卡片通常比内存页面小。JVM 维护一个卡片映射,其中每个卡片对应一个比特(或在某些实现中是字节)。每次在堆中的对象中修改指针字段时,将设置该卡片的卡片映射中的相应位。”


由于没有直接观察应用程序,例如考虑最近的传入和精细化线程处理工作的速率以及下一个垃圾回收的预期时间,精细化线程控制在防止太多工作留在收集暂停期间方面表现得比较激进。这种行为不仅浪费了精细化线程中的 CPU 循环,而且还带来了另一个缺点:Java 堆上留下了很少的未精细化的 card。虽然这听起来有好处,但在某个水平以下,这样处理可能适得其反。当有一个新的未访问 card 时,写入障碍需要执行更多的工作,如此处所述,比如果 card 留在队列中以供以后处理要多。


精细化线程的额外活动不仅消耗了 CPU 资源,而且 G1 反复精细化相同的 card 而没有减少暂停期间留下的工作。


该更改考虑到 mutator 活动能够更好地在暂停之间分配精细化线程活动,并将更多的 card 留在精细化任务队列中更长时间,从而减少了新 card 的生成速率并更确定地实现了用户的意图(即 -XX:G1RSetUpdatingPauseTimePercent)。最终,这通常需要比应用程序中少一些 CPU 周期,从而提供更好的吞吐量。


与旧精细化控制相关的几个 G1 垃圾收集器选项被废弃,当使用它们时,VM 会在启动时退出。发行说明中详细说明了它们。


3、G1 使用本地分配缓冲区(PLAB)来减少垃圾回收暂停期间的同步开销。


基于最近的分配模式调整 PLAB 的大小,以减少垃圾回收暂停期间这些缓冲区中未使用的空间。如果没有太多的分配需求会进行收缩,否则就会增长。这种每个收集暂停的自适应调整对于在垃圾回收之间具有相当恒定的分配的应用程序非常有效;然而,如果是突发性分配,这种方法则不起作用。PLAB 将在垃圾回收后的几个垃圾回收中过大时会浪费空间,或者在分配激增时过小浪费 CPU 循环重新加载 PLAB。


在某些平台上我们注意到非常长的暂停峰值,范围在几秒钟左右。JDK-8288966 中的更改添加了一些相当激进的 PLAB 调整,以在垃圾回收期间对抗这些情况。


4、JDK 20 投入了大量精力来改进用于调整年轻代大小的预测,这最终负责垃圾回收所需的时间


详细信息可查看下面的 bug 报告:

https://bugs.openjdk.org/browse/JDK-8296419?jql=labels%20%3D%20gc-g1-prediction


预测方面的改进使得 G1 可以更好地观察暂停时间目标(由 -XX:MaxGCPauseMillis 指定)。这样可以减少暂停时间和使用可用暂停时间目标,通过每个垃圾回收使用更多的年轻代区域。这增加了暂停时间在允许的目标范围内,但可以显着减少垃圾回收的数量。这些更改应用之后,我们测量的应用程序在垃圾回收暂停中花费了 10-15% 的时间。


5、JDK 20 默认禁用预防性垃圾回收(JDK-8293861)。


预防性垃圾回收是在 JDK 19 中引入的,旨在避免 G1 在垃圾回收期间没有足够的 Java 堆内存来疏散对象(也称为“疏散失败”)。之前的疏散失败的区域处理很慢,一种观点最好是进行垃圾回收,该垃圾回收在没有这种疏散失败的情况下进行,以便它释放足够的内存以完全避免这些疏散失败。


问题是如何正确地预测这种情况。G1 用于确定是否启动预防性收集的预测证明是次优的,并经常不必要地过早地启动预防性收集,导致浪费了许多时间。还有许多情况下不会被触发预防性收集,导致应用程序遇到疏散失败。最后,这种垃圾回收使垃圾回收变得更加没有规律,一旦发生,通常会使预测更加困难。


6、JDK-8297247 引入了名为“G1 Concurrent GC”的新的 GarbageCollectorMXBean。


新的 GarbageCollectorMXBean 能够报告 G1 Remark 和 Cleanup 暂停的发生和持续时间。当暂停发生时,还会更新了 G1 Old Gen MemoryManagerMXBean 内存池信息。


总之,我认为这些重要的垃圾收集更新值得升级,即使其中一些更新要等到 JDK 21 也值得考虑。


接下来会有哪些变化


JDK 21 的工作已在进行时。下面列举了一些已经集成或正在开发中的一些变化。通常没有人能保证它们一定会出现在下一个版本中,当然已经集成的改变很可能会保留;)


在改进细化线程控制之后,JDK-8225409 删除了 Hot Card Cache。这个数据结构在某种程度上是解决了上述问题的一种解决方法,即细化过于激进并且保持 card 不细化更有优势。在这种机制下,对于每个 card,G1 保留了一个计数器,用来记录它在这个 mutator 周期中被细化的次数,如果该计数超过阈值,则该卡片不会被细化,并保留在一个小的固定大小的环形缓冲区中,直到由于溢出或垃圾回收而从中删除。 在 JDK 20 细化线程控制改变之后,我们无法再测量 Hot Card Cache 带来的任何影响。当前的细化控制似乎足够 lazy(延迟加载),以吸收  Hot Card Cache 功能。 这为其他用途释放了 0.2% 的 Java 堆大小的本机内存。


此外,正在努力改善 G1 在区域级碎片的回收工作。目前,如果 G1 即使在进行 Full GC 后仍然找不到连续的内存范围来分配巨型对象,尽管在聚合中会有足够的内存可用,但是 VM 会退出并引发 OutOfMemoryException。这个 PR 更改了“最后的防线”G1 Full Collection 的行为,以移动巨型对象以创建更多连续内存。这在许多情况下应该避免 OutOfMemoryException,但代价是牺牲了长期的 Full GC。 由于 G1 Full GC 仅在进行了常规 G1 完整收集后立即发生,因此延长该 GC 以避免 VM 故障似乎是可接受的。


为了避免 G1 对未能疏散的区域(或在未来被固定)淹没老年代,允许 G1 尽快在生成后的任何垃圾回收时疏散这些老年代。 对于未能疏散的区域,当前的策略是将它们变成老年代,这意味着 G1 不能再分配它们,尽管它们通常只包含少量活跃的对象。这些也没有记忆集,因此从它们中回收空间的唯一方法是等待下一个并发标记完成。如果许多区域在多次 GC 期间未能疏散,那么 Java 堆将很快填满这些通常非常轻松占用的区域,这很容易导致完全 GC。 这个更改将完全打破先前的假设,即仅限年轻代的 GC 将永远不会对老年代 GC。尽管从技术上讲,G1 自 JDK 8u65 开始已经尝试收集一些巨型对象,这些是老年代对象,但是这种假设已经很长时间没有被严格遵守。


JDK-8297639 移除了一些预防性垃圾回收的预测功能。因为这种预测的性价比降低了,额外的 GC 会带来许多问题却没有提供任何好处。


转自:Thomas Schatzl,

链接:tschatzl.github.io/2023/03/14/jdk20-g1-parallel-gc-changes.html



- EOF -

推荐阅读  点击标题可跳转

1、聊聊 Java 20 的新功能

2、新一代垃圾回收器ZGC的探索与实践

3、从 JDK 8 到 JDK 18,Java 垃圾回收的十次进化


看完本文有收获?请转发分享给更多人

关注「ImportNew」,提升Java技能

点赞和在看就是最大的支持❤️


相关阅读

  • 鹦鹉不仅会说话,还会“打高尔夫球”

  • 提起聪明的动物,你可能会说猴子、海豚……但要是聊起能“玩转”工具的动物,那大家可能更多地会想到黑猩猩,可是你知不知道,除了黑猩猩以外,还有一种动物,既能说话,又能使用多种工具
  • KMM 技术在移动 App 开发中的探索与实践



  • 本文整理自百度资深研发工程师袁晗光在 QCon 2022 北京站 的演讲分享,主题为“KMM 技术在移动 App 开发中的探索与实践”。 提升效率永远是软件研发要追求的目标,让
  • 一起来学习下 Java 20 的新功能

  • 关注我,回复关键字“spring”,免费领取Spring学习资料。Java 20 发布了!自 Java 19 发布以来已经过去了六个月,因此又到了 Java 功能喷涌而出的时候了。本文将带你浏览 Java20
  • 鹿城五马:青年大行动 环境大扫除

  • 为了进一步巩固深化全国文明城市建设成果,积极营造“干净、整洁、有序”的城市环境。近日,温州市鹿城区五马街道谢池社区联合温州华侨中学青少年志愿队,共同开展“青年大行动
  • 鹿城南汇:垃圾分类“一条街” 绿色生活更有趣

  • 为展示当代社工风采,推动生活垃圾分类绿色理念深入人心。近日,温州市鹿城区南汇街道举办一场“垃圾分类一条街”居民趣味活动。本次活动,围绕“有趣、有料、有意义”的活动宗旨
  • 鹿城大南:弘扬社工文化 推进垃圾分类

  • 为弘扬社工文化,推动我区社会工作事业发展,做好未成年人和老年人关爱保护工作,近日,鹿城区大南街道组织社区开展了“推进五社联动 关爱一小一老”的国际社工节主题公益活动。结
  • 鹿城五马:劝导业务培训好 分类推进更有力

  • 为进一步推进垃圾分类工作,提高小区垃圾分类的质量和效率,强化生活垃圾分类投放、收集等工作,近日,温州市鹿城区五马街道鼓楼社区开展垃圾分类劝导员工作培训会,辖区各小区垃圾分
  • 温州乐清:生活垃圾分类培训会

  • 为更好地推进垃圾分类工作,使之成为日常生活“新时尚”,2023年3月24日上午,乐清湾临港经济开发区召开生活垃圾分类工作专题培训会,企业代表等共计100余人参加了此次培训。培训会
  • 鹿城藤桥:做好垃圾分类 为春天添一抹绿

  • 近日,温州市鹿城区藤桥镇组织温州市第三十中学上戌校区、藤桥校区400余名师生来到温州市学生实践学校,开展了一场户外垃圾分类主题课。通过参与劳动实践的方式,培养垃圾分类文

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四

最新文章

  • JAVA中如何高效的实现SQL的like语法?

  • 阿里妹导读本文主要介绍了一些主流的解析器是怎么实现like的语法逻辑,接着作者分析了几种实现方式的优劣,最终采用状态机的方式,针对场景一步一步进行性能优化。提及最近在优化
  • JDK 20 中垃圾回收的新变化

  • (给ImportNew加星标,提高Java技能)本文总结了 Hotspot 的 STW(Stop The World)垃圾收集器在 JDK 20 版本中的更新和改进。此版本不包含 GC 的任何 JEP(JDK 增强建议),但是 Generatio
  • 这个星座其实只在自己身上栽跟头

  • 这是一个新的系列,主要是谈谈那些失败的恋爱经验。经常给我留言发誓说“xx星座再理是狗”的人特别多,但是下次又谈上了的人也真的特别多。如果你仔细盘点一下自己身边的,和你关
  • 咖啡机选全自动还是半自动?

  • 通常来说,萃取一杯意式咖啡要研磨、布粉、填压、萃取、打奶,最后还得清洁粉碗。以上这些操作步骤在使用半自动咖啡机的时候,都是需要人手操作的。但是换作全自动,你只要按个按钮