JVM垃圾回收的历史演进:从GC算法到垃圾回收器选择

简介: JVM垃圾回收的历史演进:从GC算法到垃圾回收器选择

1. 初始阶段:标记-清除算法

在Java语言最初发布时,垃圾回收功能相对简单,只提供了基本的标记-清除算法。这种算法会扫描堆中的对象,并标记出活跃对象,然后清除掉未被标记的对象,释放空间。标记-清除算法的主要优点是简单直接,但它存在两个主要问题:内存碎片化和停顿时间过长。

2. 分代收集:复制-清除算法和标记-整理算法

随着Java应用程序的发展,研究人员发现大部分对象的生命周期很短暂,而只有少部分对象会长时间存活。为了更好地处理这种情况,JVM引入了分代收集的概念。分代收集将堆内存划分为不同的代,如年轻代和老年代,每个代使用不同的垃圾回收算法进行回收。


2.1 年轻代使用复制-清除算法或标记-整理算法

复制-清除算法将年轻代划分为两个相等的区域,每次只使用其中一个区域,当这个区域满时,将存活的对象复制到另一个区域中,然后清除当前区域。标记-整理算法则会在复制过程之后,对存活的对象进行整理,使得他们连续排列,从而减少碎片化。


2.2 老年代使用标记-整理算法或标记-清除-整理算法

标记-整理算法与年轻代相似,但应用于更大的内存空间。标记-清除-整理算法首先标记出存活对象,然后清除未被标记的对象,并对存活对象进行整理。


分代收集的设计思想是根据对象的特性和生命周期来选择合适的垃圾回收算法,以提高效率。


2.3 分代收集存在的问题

分代收集中的复制-清除算法和标记-整理算法虽然在一定程度上改善了垃圾回收的效率和内存管理,但也存在一些问题:


1) 内存浪费: 复制-清除算法中,需要将存活对象从一个区域复制到另一个区域,这意味着需要有足够的额外空间来存放复制后的对象。如果对象的存活率较高,就会导致大量的内存浪费。


2) 内存碎片化: 复制-清除算法和标记-整理算法都会导致内存碎片化的问题。复制-清除算法中,存活对象会被复制到另一个区域,而原来的区域则会出现大量的空闲内存,形成碎片化。标记-整理算法中,存活对象会被移动到连续的位置,但也可能造成原本连续的内存空间变得不连续,导致碎片化。


3) 停顿时间过长: 复制-清除算法和标记-整理算法在回收垃圾对象时,需要停止应用程序的执行。尤其是在老年代进行垃圾回收时,会导致较长的停顿时间,影响应用程序的响应性能。


4) 对象迁移开销: 复制-清除算法中,存活对象需要被复制到另一个区域,这涉及到对象迁移的开销。大规模的对象迁移可能会导致较大的性能开销。


需要注意的是,虽然这些问题存在,但在实际应用中,复制-清除算法和标记-整理算法仍然是非常有效的垃圾回收算法,并且在一些场景下表现出色


3. 并发垃圾回收

随着多核处理器的普及和应用程序的复杂性增加,传统的垃圾回收算法开始面临性能瓶颈。为了提高垃圾回收的效率,JVM引入了并发垃圾回收技术。


并发垃圾回收可以在应用程序执行的同时进行垃圾回收操作,减少了停顿时间。例如,G1垃圾回收器使用分区算法,将堆内存划分成多个区域,并使用多线程并发地进行垃圾回收操作。这种技术可以显著减少长时间的停顿,提高系统的响应性能。


并发垃圾回收通过使用多线程和智能的算法,允许在应用程序执行时进行垃圾回收操作。它可以将垃圾回收任务与应用程序的工作任务并行执行,从而减少了停顿时间,提高了系统的响应性能。

并发垃圾回收的关键技术

  1. 分区算法:并发垃圾回收使用了分区算法,将堆内存划分为多个区域。每个区域可以独立地进行垃圾回收操作,以实现并发执行。这种分区算法可以有效地减少垃圾回收的停顿时间。
  2. 并发标记:并发垃圾回收首先进行对象的标记阶段。在这个阶段,可以使用多个线程对堆中的对象进行标记,标记出存活的对象。这个过程可以与应用程序的执行并发进行,减少了停顿时间。
  3. 并发清理:在并发标记完成后,垃圾回收器可以开始清理未被标记的垃圾对象。这个阶段也可以与应用程序并发执行,进一步减少停顿时间。
  4. 并发重置:在清理阶段完成后,需要对垃圾回收器进行一些状态的重置操作,以便下一次的垃圾回收。这个重置过程也可以并发进行,不会影响应用程序的执行。

并发垃圾回收技术的引入可以显著减少长时间的停顿,提高系统的响应性能。然而,并发垃圾回收也会带来一些额外的开销,例如线程同步和内存占用等。因此,在选择使用并发垃圾回收时,需要综合考虑应用程序的特点和硬件环境的限制,以确保获得最佳的性能和用户体验。

4. 低延迟垃圾回收

随着实时应用程序和云计算的兴起,对垃圾回收的延迟要求也越来越高。JVM开始关注低延迟垃圾回收技术,以减少对应用程序响应时间的影响。

一些新的垃圾回收器,如ZGC和Shenandoah,通过使用读屏障和写屏障等技术,实现了非常短暂的停顿时间,从而满足了实时应用程序的需求。这些垃圾回收器设计了更加智能的算法和数据结构,以最小化对应用程序的干扰。


低延迟垃圾回收是一种垃圾回收技术,旨在以最小的停顿时间来执行垃圾回收操作。传统的垃圾回收算法可能会引起较长的停顿时间,影响应用程序的实时性和响应性能。为了解决这个问题,低延迟垃圾回收技术被引入。

低延迟垃圾回收技术

分代回收:分代回收是一种常见的低延迟垃圾回收技术。它将堆内存划分为不同的代,通常是新生代和老年代。新生代中的对象生命周期较短,因此可以使用较短的停顿时间进行回收。而老年代中的对象生命周期较长,可以使用相对较长的停顿时间进行回收。通过这种方式,可以在保证系统性能的同时,最小化垃圾回收的停顿时间。


并发标记清除:并发标记清除是一种低延迟垃圾回收算法,它允许在应用程序执行的同时进行垃圾回收操作。在并发标记阶段,垃圾回收器通过多线程对存活对象进行标记,而不需要停止应用程序的执行。在并发清除阶段,未被标记的垃圾对象会被清理。通过并发执行垃圾回收操作,可以减少停顿时间,提高系统的响应性能。


增量式回收:增量式回收是一种将垃圾回收过程分解为多个小步骤的低延迟垃圾回收技术。它允许在应用程序执行的间隙中进行垃圾回收操作。例如,在每次垃圾回收时,只执行一小部分的标记或清理工作,然后让应用程序继续执行。通过将垃圾回收过程分散到多个小步骤中,可以减少每次停顿的时间,从而实现低延迟的垃圾回收。


低延迟垃圾回收技术的引入可以显著降低垃圾回收的停顿时间,提高应用程序的实时性和响应性能。然而,低延迟垃圾回收也可能带来一些额外的开销,如增加的线程同步和内存占用等。因此,在选择使用低延迟垃圾回收时,需要综合考虑应用程序的特点和硬件环境的限制,以平衡性能和资源消耗。


5. 垃圾回收器的选择

随着JVM的发展,出现了多种不同类型的垃圾回收器,每种垃圾回收器都有其适用的场景和优缺点。开发人员可以根据应用程序的需求和硬件环境的特点,选择合适的垃圾回收器进行使用。


常见的垃圾回收器有Serial、Parallel、CMS、G1、ZGC和Shenandoah等。这些垃圾回收器在算法、性能和停顿时间方面各有不同,开发人员需要根据具体情况进行选择。


选择适合的垃圾回收器对于应用程序的性能和响应性能至关重要。不同的垃圾回收器具有不同的特点和优势,因此需要根据应用程序的需求、硬件环境和性能目标来选择。

5.1常见的垃圾回收器及其特点

5.1.1 Serial 垃圾回收器:

Serial 回收器是一种单线程的垃圾回收器,它会暂停应用程序的执行来进行垃圾回收操作。它适用于较小的应用程序或单核处理器环境,因为它的停顿时间相对较长,但内存占用较低。

5.1.2 Parallel 垃圾回收器

Parallel 回收器是多线程的垃圾回收器,它可以利用多个处理器来并行执行垃圾回收操作。它适用于多核处理器环境,可以显著减少垃圾回收的停顿时间,提高系统的吞吐量。

5.1.3 CMS (Concurrent Mark Sweep) 垃圾回收器

CMS 回收器是一种并发垃圾回收器,它允许在应用程序执行的同时进行垃圾回收操作。它适用于对停顿时间有较高要求的应用程序,因为它的停顿时间相对较短。但是,CMS 回收器可能会导致一些额外的开销,如碎片化和处理器资源的抢占。

5.1.4 G1 (Garbage-First) 垃圾回收器

G1 回收器是一种基于分区的垃圾回收器,它可以以较低的停顿时间进行垃圾回收操作。它适用于大型内存和多核处理器环境,可以更好地管理堆内存,并减少停顿时间的波动。

5.1.5 ZGC

ZGC 是一种低延迟垃圾回收器,它的设计目标是在几毫秒的范围内最大程度地减少停顿时间。它使用了并发标记和并发整理的技术,允许在应用程序执行期间进行垃圾回收操作。ZGC 适用于需要高度可预测和短暂的停顿时间的应用程序,尤其是需要大堆内存的场景。

5.1.6 Shenandoah

Shenandoah 是另一种低延迟垃圾回收器,它通过采用并发标记、并发清理和并发压缩的方法来实现低延迟。Shenandoah 的目标是在不同的堆大小下都提供可接受的停顿时间,并尽量避免长时间的停顿。Shenandoah 适用于对停顿时间要求非常苛刻的应用程序。

5.2 选择垃圾回收器时考虑的因素

  1. 停顿时间:如果应用程序对停顿时间要求较高,可以选择并发或增量式回收器,如CMS或G1。
  2. 吞吐量:如果应用程序对吞吐量要求较高,可以选择多线程回收器,如Parallel 或 G1。
  3. 内存占用:如果应用程序对内存占用要求较低,可以选择单线程回收器,如Serial。
  4. 硬件环境:根据处理器的核数和内存大小来选择适合的垃圾回收器。

综上所述,选择合适的垃圾回收器需要综合考虑应用程序的需求、硬件环境和性能目标。通过评估不同垃圾回收器的特点和优势,可以选择最适合特定应用程序的垃圾回收器,以实现最佳的性能和用户体验。


6. 结语

JVM垃圾回收技术经历了从简单的标记-清除算法到分代收集、并发垃圾回收和低延迟垃圾回收的演进过程。这些技术的出现和发展,使得Java应用程序能够更高效地管理内存,提高性能,并满足不同类型应用程序的需求。在实际开发中,开发人员应根据应用程序的特点和需求,选择合适的垃圾回收器,以达到最佳的性能和用户体验

相关文章
|
25天前
|
存储 算法 Oracle
极致八股文之JVM垃圾回收器G1&ZGC详解
本文作者分享了一些垃圾回收器的执行过程,希望给大家参考。
|
2月前
|
Arthas 监控 Java
(十一)JVM成神路之性能调优篇:GC调优、Arthas工具详解及各场景下线上最佳配置推荐
“在当前的互联网开发模式下,系统访问量日涨、并发暴增、线上瓶颈等各种性能问题纷涌而至,性能优化成为了现时代开发过程中炙手可热的名词,无论是在开发、面试过程中,性能优化都是一个常谈常新的话题”。
171 3
|
2月前
|
存储 算法 安全
(八)JVM成神路之GC分区篇:G1、ZGC、ShenandoahGC高性能收集器深入剖析
在《GC分代篇》中,我们曾对JVM中的分代GC收集器进行了全面阐述,而在本章中重点则是对JDK后续新版本中研发推出的高性能收集器进行深入剖析。
94 12
|
2月前
|
运维 Java Linux
(九)JVM成神路之性能调优、GC调试、各内存区、Linux参数大全及实用小技巧
本章节主要用于补齐之前GC篇章以及JVM运行时数据区的一些JVM参数,更多的作用也可以看作是JVM的参数列表大全。对于开发者而言,能够控制JVM的部分也就只有启动参数了,同时,对于JVM的性能调优而言,JVM的参数也是基础。
|
2月前
|
算法 安全 Java
(七)JVM成神路之GC分代篇:分代GC器、CMS收集器及YoungGC、FullGC日志剖析
在《GC基础篇》中曾谈到过分代以及分区回收的概念,但基础篇更多的是建立在GC的一些算法理论上进行高谈阔论,而本篇则重点会对于分代收集器的实现进行全面详解,其中会涵盖串行收集器、并行收集器、三色标记、SATB算法、GC执行过程、并发标记、CMS收集器等知识,本篇则偏重于分析GC机制的落地实现,也就是垃圾收集器(Garbage Collector)。
|
1月前
|
算法 Java 应用服务中间件
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
|
1月前
|
存储 监控 算法
深入解析JVM内部结构及GC机制的实战应用
深入解析JVM内部结构及GC机制的实战应用
|
16天前
|
算法 BI Serverless
基于鱼群算法的散热片形状优化matlab仿真
本研究利用浴盆曲线模拟空隙外形,并通过鱼群算法(FSA)优化浴盆曲线参数,以获得最佳孔隙度值及对应的R值。FSA通过模拟鱼群的聚群、避障和觅食行为,实现高效全局搜索。具体步骤包括初始化鱼群、计算适应度值、更新位置及判断终止条件。最终确定散热片的最佳形状参数。仿真结果显示该方法能显著提高优化效率。相关代码使用MATLAB 2022a实现。
|
16天前
|
算法 数据可视化
基于SSA奇异谱分析算法的时间序列趋势线提取matlab仿真
奇异谱分析(SSA)是一种基于奇异值分解(SVD)和轨迹矩阵的非线性、非参数时间序列分析方法,适用于提取趋势、周期性和噪声成分。本项目使用MATLAB 2022a版本实现从强干扰序列中提取趋势线,并通过可视化展示了原时间序列与提取的趋势分量。代码实现了滑动窗口下的奇异值分解和分组重构,适用于非线性和非平稳时间序列分析。此方法在气候变化、金融市场和生物医学信号处理等领域有广泛应用。
|
17天前
|
资源调度 算法
基于迭代扩展卡尔曼滤波算法的倒立摆控制系统matlab仿真
本课题研究基于迭代扩展卡尔曼滤波算法的倒立摆控制系统,并对比UKF、EKF、迭代UKF和迭代EKF的控制效果。倒立摆作为典型的非线性系统,适用于评估不同滤波方法的性能。UKF采用无迹变换逼近非线性函数,避免了EKF中的截断误差;EKF则通过泰勒级数展开近似非线性函数;迭代EKF和迭代UKF通过多次迭代提高状态估计精度。系统使用MATLAB 2022a进行仿真和分析,结果显示UKF和迭代UKF在非线性强的系统中表现更佳,但计算复杂度较高;EKF和迭代EKF则更适合维数较高或计算受限的场景。