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

经历了数千次改进,Java的垃圾回收在吞吐量、延迟和内存大小方面有了巨大的进步。

2014年3月JDK 8发布,自那以来JDK又连续发布了许多版本,直到今日的JDK 18是Java的第十个版本。借此机会,我们来回顾一下HotSpot JVM的垃圾回收器的发展全过程。

关于垃圾回收、度量和取舍

HotSpot JVM中负责管理应用程序堆的组件叫做“垃圾回收器”(Garbage Collector,即GC)。GC负责管理应用程序堆对象的整个生命周期,从应用程序分配内存到内存被回收,都由GC负责。

从高层来看,JVM垃圾回收算法的最基本功能如下:

  • 当应用程序请求分配内存时,GC负责提供内存。提供内存的过程应尽可能快。

  • GC检测应用程序不再使用的内存。这个操作也应当十分高效,不应消耗太多时间。这种不再使用的内存称为“垃圾”。

  • GC将同一块内存再次提供给应用程序,最好是“实时”,也就是要快。

好的垃圾回收算法还有更多的需求,但这三条是最基本的,也足以支撑本文的讨论了。

满足这些需求有很多方法,但很不幸,我们并没有一蹴而就的方法,也没有能一次性解决所有需求的方法。因此,JDK提供了多种垃圾回收算法以供选择,每种算法适用于不同的场景。这些算法的实现基本上可以根据吞吐量、延迟和内存大小这三个性能度量,以及对应用程序的影响进行归类。

  • 吞吐量指的是单位时间内能够完成的工作量。在此语境下,垃圾回收算法的优劣取决于能在单位时间内完成的回收工作量,这些算法可以让Java应用程序实现更高的吞吐量。

  • 延迟指的是单次操作所需时间。垃圾回收算法需要尽可能减小延迟。在垃圾回收的语境下,关键点就是垃圾回收期是否会导致暂停、暂停的范围,以及暂停的时长。

  • 在垃圾回收的语境下,内存大小指的是为了让垃圾回收期正常工作,需要在正常的应用程序堆内存之外,再额外占用多少内存。如果GC(或更一般地,JVM)需要的内存很少,就可以给应用程序堆留出更多内存。

这三个度量是互相关联的:高吞吐量的垃圾回收器可能会严重影响延迟(但对应用程序的影响最小)。为了降低内存消耗,我们需要采用在其他度量方面不是那么出色的算法。延迟较低的回收期需要并行进行更多工作,或以更小的单位进行工作,这就会消耗更多处理器资源。

这些关系通常可以画成一个三角形,如图1所示。每个垃圾回收算法占据三角形的一个角。

图1. GC性能度量三角

提高GC在某方面的表现,通常会导致其他方面的表现降低。

JDK 18中的OpenJDK GC

OpenJDK提供了五种GC,分别专注于不同的性能度量。表1列出了GC的名称、专注领域,以及实现特定特性所使用的核心概念。

表1. OpenJDK的五种GC

Parallel GC是JDK 8以及更早版本的默认回收期。它专注于吞吐量,尽快完成工作,而很少考虑延迟(暂停)。

Parallel GC会在STW(全局暂停)期间,以更紧凑的方式,将正在使用中的内存移动(复制)到堆中的其他位置,从而制造出大片的空闲内存区域。当内存分配请求无法满足时就会发生STW暂停,然后JVM完全停止应用程序运行,投入尽可能多的处理器线程,让垃圾回收算法执行

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值