java虚拟机面试干货【伍】_垃圾回收:回收算法


上篇文章:java虚拟机面试干货【肆】_垃圾回收:判断条件


上篇文章我们分析了GC中对要回收对象的判断条件,这篇文章我们说说GC回收算法。


标记-清除算法


即mark-sweep算法。通过两个阶段完成,一是标记阶段,筛选出已经没有关联到GC Roots调用链的对象;二是清除,将这些标记处的对象删除。示意图如下:




但这个算法有2个问题:一是效率太低;二是内存碎片。产生的大量内存碎片因空间不连续,会导致再分配大对象时重新触发一次GC。


复制算法


将内存空间分为两块,每次只使用其中一块的空间。当进行GC回收时,将存活的对象复制到另一块上,然后将使用过的这块全部清理。示意图如下:



使用该算法的代价是牺牲了一半的存储空间,属于空间换时间的实现。在Hotspot实现中,新生代的GC回收即使用了复制算法,这块我们后面就讲。


标记-整理算法


即mark-conpact算法,标记过程和标记-清除算法一样,但后续步骤不是将对象清理,而是将存活的对象向一端移动,然后清理掉边界之外的所有对象。示意图如下:




适用于对象存活率较高的情景,HotSpot的老年代即使用该算法。


分代回收算法


即分代收集(Generational Collection),基本思想就是根据对象存活周期的不同将内存划分为几块。在JVM的实现中,就把java堆划分为了新生代老年代,其中新生代还包括Eden区Survivor区。下面尝试分析:


Eden区


希腊语伊甸园,位于新生代,大多数对象被声明时保存在这个区域。当Eden区空间不足时,触发minor GC,将Eden区的存活对象移动到新的Survivor区。由此可见,Eden区采用复制算法。


Survivor区


意为幸存者,是新生代和老年代的缓冲区域。分为Survivor0(S0)和Survivor1(S1)两部分,和Eden区大小比例默认是1:1:8。当发生Minor GC时,会将存活的对象移动到S0内存区域,并清空Eden区域,当再次发生Minor GC时,将Eden和S0中存活的对象移动到S1内存区域。


存活对象会反复在S0和S1之间移动,当对象从Eden移动到Survivor或者在Survivor之间移动时,对象的GC年龄自动累加,当GC年龄超过默认阈值15时,会将该对象移动到老年代,可以通过参数-XX:MaxTenuringThreshold 对GC年龄的阈值进行设置。


老年代


老年代的空间大小即-Xmx 与-Xmn 两个参数之差,用于存放经过几次Minor GC之后依旧存活的对象。当老年代的空间不足时,会触发Major GC/Full GC,速度一般比Minor GC慢10倍以上。老年代采用标记-整理算法。


当老年代的空间不足时”的判断时间在发生Minor GC之前,虚拟机会先检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立,则虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许,那么会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小,如果大于,将尝试着进行一次Minor GC,尽管这次Minor GC是有风险的;如果小于,或者HandlePromotionFailure设置不允许冒险,那这时也要改为进行一次Full GC。


三种垃圾回收


很多书上都说了垃圾回收分为minor GC、major GC和full GC三种,区别如下:


minor GC:新生代回收。

major GC:老年代回收。

full GC:整个堆空间回收。


其实后来整理发现,major GC和full GC的界限并不是那么明显,比如上文整理的full GC就是由minor GC触发的,而目的也是为了老年代的回收。相比于对这些概念性的较真,不如更关心下实际生产中的使用。


full GC的触发条件还有:

1.System.gc();

2.老年代空间不足。若full GC后仍不足,则抛出OOM:Java Heap Space;

3.永久代空间不足。若full GC后仍不足,则抛出OOM:Perm Gen;

4.CMS GC时出现Promotion Fail和Concurrent Mode Failer,即minor GC后,servivor放不下,老年代也放不下;

5.统计得到的minor GC晋升老年代的平均大小大于老年代剩余空间;


下文我们说说常见的GC回收器


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值