Java回收功能从 JDK8到JDK18的变化
经历了千百次改进,Java的垃圾回收在吞吐量、延迟和内存大小方面有了巨大的进步。
Java回收功能从 JDK8到JDK18的变化
关于垃圾回收、测量和选择
HotSpotJVM负责管理应用程序堆的组件称为“垃圾回收器”(GarbageCollector,即GC)。GC负责管理应用程序堆对象的整个生命周期,从应用程序分配内存到回收内存,都是由应用程序分配的GC负责。
从高层来看,JVM垃圾回收算法最基本的功能如下:
当应用程序要求分配内存时,GC负责提供内存。提供内存的过程应
GC检查应用程序中不再使用的内存。此操作也应非常有效,不应消耗太多时间。这种不再使用的内存称为“垃圾”。
GC再次向应用程序提供相同的内存,最好是“即时”也就是要快。
好的垃圾回收算法还有更多的需求,但是这三个是最基本的,也足以支持本文的讨论。
满足这些需求的方法有很多,但不幸的是,我们没有办法一蹴而就,也没有办法一次处理所有需求。JDK它带来了各种垃圾回收算法供选择,每种算法适用于不同的场景。这些算法的实现基本上可以根据吞吐量、延迟和内存大小以及应用程序的影响进行分类。
吞吐量是指单位时间内可以完成的工作量。在这种情况下,垃圾回收算法的质量取决于单位时间内可以完成的回收工作量,这可以使Java应用程序实现更高的吞吐量。
延迟是指一次操作所需的时间。垃圾回收算法需要尽可能减少延迟。在垃圾回收的背景下,关键是垃圾回收期是否会导致暂停、暂停范围和暂停时间。
在垃圾回收的背景下,内存大小是指在正常的应用程序堆内存之外,为了使垃圾回收期正常工作,需要多少额外的内存。GC(或更一般,JVM)需要的内存很少,可以为应用程序堆留出更多的内存。
这三种措施是相互关联的:高吞吐量的垃圾收集器可能会严重影响延迟(但对应用程序的影响最小)。为了减少内存消耗,我们需要选择在其他测量方面不太好的算法。低回收期的延迟需要更多的平行工作或更小的单位,这将消耗更多的处理器资源。
提升GC在某些方面的表现,通常会导致其他方面的表现减少。
JDK18里的OpenJDKGC
OpenJDK带来了五种GC,他们致力于不同的性能测量。表1列出了GC用于实现特定特征的核心概念名称、重点领域和核心概念。
ParallelGC是JDK8及早期版本的默认回收期。它致力于吞吐量,尽早完成工作,很少考虑延迟(暂停)。
ParallelGC会在STW在(全局暂停)期间,使用中的内存以更紧凑的方式移动(复制)到堆中的其他位置,然后创建一个大的空闲内存区域。当无法满足内存分配请求时,就会发生这种情况STW暂停,随后JVM完全停止应用程序运行,尽可能多地投资Cpu在此过程中,让垃圾回收算法执行内存压缩工作,然后分配请求的内存,最后恢复应用程序执行。
ParallelGC它也是一个分代回收器,旨在最大限度地提高垃圾回收效率。本文稍后将详细讨论分代回收的思路。
G1GC是JDK默认回收期后99。G试图平衡吞吐量和延迟。一方面,在STW在暂停期间,内存回收工作仍将使用分代实施,以最大限度地提高效率ParallelGC同样;不过,它也会尽量避免在暂停期间需要更长时间的操作。
G1的长期操作将与应用程序并行进行,即在应用程序运行时通过多线程执行。这可以大大降低暂停,成本是整体吞吐量将略有减少。
ZGC和ShenandoahGC致力于用吞吐量换取延迟。这两个回收器将尝试在不进行明显暂停的情况下完成所有垃圾回收工作。目前,两者都不是代代的。他们的非实验版本JDK15和JDK12引入。
SerialGC致力于内存大小和启动时间。GC喜欢更简单,更慢ParallelGC,它在STW在暂停期间,只有一个过程用于完成所有工作。堆也是按代理组织的。SerialGC内存占用较少,启动速度较快。因为它比较简单,所以更适合小型、短时间运行的应用。
OpenJDK还提供了另一个名称Epsilon的GC。为什么没有在表1中列出?Epsilon只执行内存分配,从不回收内存,所以不满意GC所有条件。但是,,Epsilon适用于一些非常特殊的应用程序。