JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。

大厂面试真题:GC 算法有多少种?各自优缺点是什么?年轻代和年老代选择哪种算法最优?

     首先回顾一个图,也就是.class文件的类加载过程,以及线程执行、java内存模型图。看过系列1、2、3三篇文章的同学,大脑先回顾一遍类加器类型、双亲委派机制、如何打破双亲委派机制、GC内存划分、各个区域存放什么数据、以及给你一段代码要知道具体如何执行,对象什么时候被回收的逻辑。有道是,磨刀不误砍柴工,温故而知新,巩固基础,修炼JVM调优进阶核心技术。


       然后堆内存空间区域划分,在上一篇文章系列2以及说过,具体如下图,再回顾一下,年轻代分了Eden区和S1、S2区,堆内存里除了年轻代,其他都是老年代空间。

     今天重点讲的就是堆内存的GC算法以及GC处理过程,一步步来,希望本系列(预计100篇)结题的时候,有缘刷到的同学都有所收获,都能做JVM线上问题排查和JVM调优。


一、年轻代GC 复制算法

      我们知道,当一个新对象要存到堆内存里,这里暂且不说大对象,对象都是优先放到年轻代的Eden区。那随着时间推移,如下图Eden区满了,怎么办?答案:那肯定是要发生YGC,也就是Minor GC。

YGC采用的是什么GC算法?

答: 复制算法。

那为什么选这个算法?

答:稍等,后文解答。

复制算法核心逻辑是:将GC发现有GC Roots也就是还存活的对象,统一挪到S区。


1.1 复制算法的三个阶段

1、标记阶段

从GC Roots集合开始,标记还存活被引用的对象;

2、转移阶段

即把存活对象复制到新的内存地址上。

3、重定位阶段

因为复制转移导致对象的地址发生了变化,在这个重定位阶段,要把所有指向对象的旧地址的指针调整为新内存地址。

1.2 举例具体YGC过程

1、最开始,所有新对象在Eden区,发生YGC后,将存活的对象放到S1区;

2、再发生YGC,就把Eden区和S1区的存活对象,放到S2区。新对象继续放Eden区;

3、再发生YGC,就把Eden区和S2的存活对象,放到S1区。新对象继续放Eden区;

2和3反复。

如下图,当YGC结束后,Eden区就变干净,S区的1或2会存放存活对象,而另一个S区也是干净的。


1.3 复制算法有什么优点?

实现简单,另外由于没有标记和清除过程,执行效率高(毕竟存活的对象总是很少),而且复制对象到S区,使得内存空间总是连续的,没有空间碎片,那内存碎片问题就解决了。另外通过Eden+S1+S2三个区,而且是8:1:1的空间比例,内存利用率也很高,高达90%,仅仅浪费10%,相比传统复制算法只分两个区(5:5占比划分),内存利用率大幅提升。

1.4 复制算法的缺点是什么?

唯一缺点,就是没有100%利用内存,会有一些浪费。目前年轻代的这种分区复制算法,以及非常优秀,仅浪费10%左右内存,这个参数可以根据实际情况进行JVM调优。

看完复制算法的优缺点,这回就知道年轻代为什么适合用复制算法了:核心是年轻代每次GC后存活的对象很少,用复制算法效率高。

1.4 年轻代对应的垃圾回收器有哪些?

年轻代对应的GC回收器有Serial 垃圾回收器、ParNew垃圾回收器。


二、老年代GC 标记-整理算法

    老年代的GC,也就是FullGC,那FullGC什么时候会触发呢?

    一般就是当YGC之后发现存活对象很多,S区放不下了,或者触发某些规则,必须放老年代那边。这时候会去检查老年代还有多少空闲空间,如果发现老年代那边的空闲空间放不下,那就要先发生一个FullGC腾空间。

     老年代FullGC主流采用的是标记-整理算法,核心原理大概是这样:

 把老年代里的存活对象标记处理,然后清理那些已经可以GC回收的对象。最后把相关存活对象归集整理放在一篇连续内存区域,避免有内存碎片。

      老年代的这个标记回收算法,是非常慢的,效率比年轻代回收慢一个数量级。

      老年代对应的GC回收器有Serial Old垃圾回收器、CMS垃圾回收器。

2.1 标记-整理算法过程具体说说

1、标记(Marking)

与其他算法标记类型,从根对象开始,标记出所有存活的对象。

2、整理(Compacting)

在标记清除可以被回收的对象后,将所有存活的对象向一片连续内存移动,这样可以消除内存碎片提高老年代的内存使用率。

3、更新引用

在整理过程中,由于对象位置有挪动修改,所以对象内部的引用也需要进行同步更新,以指向移动后的对象地址。

  发现这个过程和复制算法是差不多的,核心差异在整理那,不过那细讲也要写一篇来说,后续出文再讲。

2.2 标记整理算法的优缺点是什么?

优点:解决了标记-清理算法存在的内存碎片问题,使得内存空间更加紧凑,提高了内存利用率。

缺点:由于需要对存活对象进行移动,这会导致一定的性能开销,降低了GC效率。

2.3 老年代为什么不用复制算法?

     老年代的标记整理算法竟然效率这么低,为啥不该用复制算法呢?

      这是因为老年代的对象存活率会较高,每次FGC,很可能有超过50%对象还会存活。如果存活的对象多,那复制操作的效率也一样会变低。同样,有一个的标记清除算法也可以应用在老年代中,但是它效率和标记整理算法差不多,也不高,且在内存回收后容易产生大量内存碎片。因此标记整理算法(Mark-Compact)算法,是老年代较优的选择。

本文仅重点介绍分区复制算法、还有标记整理算法,除了这两个还有标记-清除算法(Mark-Sweep)、分代收集算法(Generational Collection)。这里不再赘述。


推荐阅读:

1、JVM进阶调优系列(3)堆内存的对象什么时候被回收?

2、JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?

3、JVM进阶调优系列(1)类加载器原理一文讲透

4、JAVA并发编程系列(13)Future、FutureTask异步小王子

目录
打赏
0
0
0
0
106
分享
相关文章
JVM实战—4.JVM垃圾回收器的原理和调优
本文详细探讨了JVM垃圾回收机制,包括新生代ParNew和老年代CMS垃圾回收器的工作原理与优化方法。内容涵盖ParNew的多线程特性、默认线程数设置及适用场景,CMS的四个阶段(初始标记、并发标记、重新标记、并发清理)及其性能分析,以及如何通过合理分配内存区域、调整参数(如-XX:SurvivorRatio、-XX:MaxTenuringThreshold等)来优化垃圾回收。此外,还结合电商大促案例,分析了系统高峰期的内存使用模型,并总结了YGC和FGC的触发条件与优化策略。最后,针对常见问题进行了汇总解答,强调了基于系统运行模型进行JVM参数调优的重要性。
JVM实战—4.JVM垃圾回收器的原理和调优
JVM实战—5.G1垃圾回收器的原理和调优
本文详细解析了G1垃圾回收器的工作原理及其优化方法。首先介绍了G1通过将堆内存划分为多个Region实现分代回收,有效减少停顿时间,并可通过参数设置控制GC停顿时长。接着分析了G1相较于传统GC的优势,如停顿时间可控、大对象不进入老年代等。还探讨了如何合理设置G1参数以优化性能,包括调整新生代与老年代比例、控制GC频率及避免Full GC。最后结合实际案例说明了G1在大内存场景和对延迟敏感业务中的应用价值,同时解答了关于内存碎片、Region划分对性能影响等问题。
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
Java虚拟机调优指南####
本文深入探讨了Java虚拟机(JVM)调优的精髓,从内存管理、垃圾回收到性能监控等多个维度出发,为开发者提供了一系列实用的调优策略。通过优化配置与参数调整,旨在帮助读者提升Java应用的运行效率和稳定性,确保其在高并发、大数据量场景下依然能够保持高效运作。 ####
68 1
JVM进阶调优系列(10)敢向stop the world喊卡的G1垃圾回收器 | 有必要讲透
本文详细介绍了G1垃圾回收器的背景、核心原理及其回收过程。G1,即Garbage First,旨在通过将堆内存划分为多个Region来实现低延时的垃圾回收,每个Region可以根据其垃圾回收的价值被优先回收。文章还探讨了G1的Young GC、Mixed GC以及Full GC的具体流程,并列出了G1回收器的核心参数配置,帮助读者更好地理解和优化G1的使用。
基于生物地理算法的MLP多层感知机优化matlab仿真
本程序基于生物地理算法(BBO)优化MLP多层感知机,通过MATLAB2022A实现随机数据点的趋势预测,并输出优化收敛曲线。BBO模拟物种在地理空间上的迁移、竞争与适应过程,以优化MLP的权重和偏置参数,提升预测性能。完整程序无水印,适用于机器学习和数据预测任务。
基于LSB最低有效位的音频水印嵌入提取算法FPGA实现,包含testbench和MATLAB对比
本项目展示了一种基于FPGA的音频水印算法,采用LSB(最低有效位)技术实现版权保护与数据追踪功能。使用Vivado2019.2和Matlab2022a开发,完整代码含中文注释及操作视频。算法通过修改音频采样点的最低有效位嵌入水印,人耳难以察觉变化。然而,面对滤波或压缩等攻击时,水印提取可能受影响。该项目运行效果无水印干扰,适合实时应用场景,核心逻辑简单高效,时间复杂度低。
基于GA遗传算法的拱桥静载试验车辆最优布载matlab仿真
本程序基于遗传算法(GA)实现拱桥静载试验车辆最优布载的MATLAB仿真,旨在自动化确定车辆位置以满足加载效率要求(0.95≤ηq≤1.05),目标是使ηq尽量接近1,同时减少车辆数量和布载耗时。程序在MATLAB 2022A版本下运行,展示了工况1至工况3的测试结果。通过优化模型,综合考虑车辆重量、位置、类型及车道占用等因素,确保桥梁关键部位承受最大荷载,从而有效评估桥梁性能。核心代码实现了迭代优化过程,并输出最优布载方案及相关参数。
基于MobileNet深度学习网络的活体人脸识别检测算法matlab仿真
本内容主要介绍一种基于MobileNet深度学习网络的活体人脸识别检测技术及MQAM调制类型识别方法。完整程序运行效果无水印,需使用Matlab2022a版本。核心代码包含详细中文注释与操作视频。理论概述中提到,传统人脸识别易受非活体攻击影响,而MobileNet通过轻量化的深度可分离卷积结构,在保证准确性的同时提升检测效率。活体人脸与非活体在纹理和光照上存在显著差异,MobileNet可有效提取人脸高级特征,为无线通信领域提供先进的调制类型识别方案。
基于模糊神经网络的金融序列预测算法matlab仿真
本程序为基于模糊神经网络的金融序列预测算法MATLAB仿真,适用于非线性、不确定性金融数据预测。通过MAD、RSI、KD等指标实现序列预测与收益分析,运行环境为MATLAB2022A,完整程序无水印。算法结合模糊逻辑与神经网络技术,包含输入层、模糊化层、规则层等结构,可有效处理金融市场中的复杂关系,助力投资者制定交易策略。
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等