JVM经典垃圾回收算法

一、标记-清除算法

该算法分为标记和清除两个阶段。标记阶段基于可达性分析,具体原理可以参照我之前的博客文章。可达性分析阶段会标记出所有存活的对象(也可以标记死亡的对象,原理类似)。在标记完成后,将回收所有的死亡对象。具体图解如下:

从图中我们可以看出这个收集方法的缺点:就是会产生大量的不连续的内存碎片,有可能提前引发一次FullGC(),进而影响其他程序的工作。除此之外,如果JAVA堆中包含了大量的对象,那么标记的过程将十分费时,同时,清理的过程会随着对象的增多而耗费更多的时间。

二、复制算法

这个算法对内存做了一个分区,将其分为新生代和老年代。一般情况下,垃圾回收的过程主要发生在新生代,老年代的对象很少发生垃圾回收(可通过FullGC()回收)。

在新生代中,将新生代分为伊甸园区(Eden),幸存者From区和幸存者To区。这三个空间的大小在HotSpot中的默认值是8:1:1。

接下来说一下这个回收方法的原理:每次分配内存,只分配给Eden区和From区。在垃圾回收时,对于Eden区和From区中的对象进行标记,标记完成后,将所有存活的对象复制到To区。之后,清除From区和Eden区中的所有对象,再将From区和To区进行交换。也就是说两个幸存者区并不是一成不变的,而是动态确定的。具体过程如下:

 

 从图中可以看出,相比于标记-清除算法,复制算法解决了内存碎片的问题,因为存活对象复制到To区的时候是顺序存储的,即一定可以保证连续性。但复制算法的最大缺点是,如果存活的对象数量过多,复制过程将非常耗时。故此方法不适合回收存活率高的内存空间。

还有一个问题,当To区的空间不足以容纳Eden区和From区中的所有对象时,将会有一部分对象晋升到老年代。

三、标记-整理算法

标记-整理算法是基于标记-清除算法演化而来的,其标记的步骤与标记-清除算法相同,但清除的过程并不是直接将死亡对象清除,而是将所有存活的对象移向一边,然后清除所有的死亡对象。

该方法相比于标记-清除算法,不会产生内存碎片,相比于复制算法,清理效率较高。但移动存活对象时,需要暂停用户进程才能进行,因此,用户体验极差。但如果不采用移动对象的手段的话,就只能维护一个空闲列表来记录来记录空闲的内存空间,开销会更大。

除了这三种以外,还有一种“和稀泥”的垃圾回收算法,就是平时多数时间都采用标记-清除算法,暂时容忍内存碎片的存在,当内存碎片大到影响对象分配时,再进行一次标记-整理算法。CMS垃圾收集器就是基于这种算法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值