搞定Java垃圾回收(三)

         在确定了哪些垃圾可以被回收后,垃圾收集器要做的事情就是开始进行垃圾回收,但是这里面涉及到一个问题是:如何高效地进行垃圾回收?由于Java虚拟机规范并没有对如何实现垃圾收集器做出明确的规定,因此各个厂商的虚拟机可以采用不同的方式来实现垃圾收集器,这里我们讨论几种常见的垃圾收集算法的核心思想。

1、标记-清除算法

标记-清除算法(Mark-Sweep)是最基础的一种垃圾回收算法,它分为2部分,先把内存区域中的这些对象进行标记,哪些属于可回收标记出来,然后把这些垃圾拎出来清理掉。
           就像上图一样,清理掉了的垃圾就变成未使用的内存区域,等待被再次使用。但也存在一个很大的问题,就是内存碎片。
上图中等方块的假设是2M,小一些的是1M,大一些的是4M。等我们回收完,内存就会切成了很多段。我们知道开辟内存空间时,需要的是连续的内存区域,这时候我们需要一个2M的内存区域,其中2个1M是没法用的。这样就导致,其实我们本身还有这么多的内存的,但却用不了。

2、复制算法

复制算法(Copying)是在标记清除算法上演化而来,解决标记清除算法的内存碎片问题。它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将还存活的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。保证了内存的连续可用,内存分配时也就不用考虑内存碎片等复杂情况,逻辑清晰,运行高效。上面的图很清楚,也很明显暴露了另一个问题就是拆分的代价实在太高

3、标记-整理算法

         标记-整理算法(Mark-Compact)的标记过程仍然与标记清除算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,再清理掉端边界以外的内存区域。
        标记-整理算法一方面在标记-清除算法上做了升级,解决了内存碎片的问题,也规避了复制算法只能利用一半内存区域的弊端。看起来很美好,但从上图可以看到,它对内存变动更频繁,需要整理的所有存活对象的引用地址,在效率上比复制算法要差很多。

4、分代收集算法(Generational Collection)

          分代收集算法严格来说并不是一种思想或理论,而是融合上述3种基本的算法思想,而产生的针对不同情况所采用不同算法的一套组合拳。对想存活期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用适当的收集算法。
         在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。
        而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用标记-清理或者标记整理算法来进行回收。
那么,另一个问题来了,那内存区域到底被分为哪几块,每一块又有什么特别适合的算法呢?请看下节!

 

参考出处:阿里巴巴中间件微信公众号

你的鼓励是我分享技术最大的动力!如有错误之处,请指正,不胜感激。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值