垃圾收集使用的基本算法

我们都知道Java虚拟机会去回收”死亡”的对象,那么这个”回收 “是怎么回收的呢?

下面介绍几种垃圾收集的基本算法

常见的垃圾收集基本算法

1、标记-清除算法(Mark-Sweep)

标记-清除算法分为”标记”和”清除”两个部分。

标记:在前面文章finalize()方法总结中已经总结过标记算法,这里就不再赘述了。简单理解一下就是虚拟机经过两次标记找出真正”死亡”的对象。

清除:清除算法也很好理解,就是将标记为”死亡”的对象回收掉。

标记-清除算法

标记-清除算法虽然简单,但是它也有一定的缺点:
- 效率低:标记和清除算法的效率都很低,标记-清除算法需要标记一次再清除一次
- 浪费空间:标记清除之后会产生大量不连续的内存碎片,浪费内存,并且可能导致没有空间分配给大内存对象从而可能导致提前一次GC

2、复制算法

为了解决标记-清除算法内存碎片的问题,复制算法就出来了。

复制算法先将内存分为大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就进行复制,将还存活的对象复制到另一块内存上,然后再将正在使用的那块内存空间一次清空。

复制算法

这样使得每次只对其中一块内存进行回收,避免了内存碎片的问题,但是复制算法的缺点也显而易见,浪费内存,一半的内存完全浪费了。

3、标记-整理算法

标记整理算法的标记过程和标记-清除算法一样,也是先标记出”死亡”的对象。

整理:整理算法会将标记为”死亡”的对象清除,然后将后面所有的对象向前移动,以解决内存碎片的问题。

标记-整理算法

至于标记-整理算法的使用场景下面再来介绍。

虚拟机的分代收集算法

分代收集算法并不是什么新的算法,而是根据对象的存活周期将上面的基本算法结合起来实现的收集算法。

1、Java中对象的存活周期

首先我们简单的了解一下Java中对象的存活周期。

我们可以按照Java中对象的存货周期将他们分为新生代和老年代:一般新建的对象都在新生代(大对象直接进入老年代),默认年龄是 1,对象每熬过一次GC,年龄都会会加 1,当年龄达到一定程度(默认15)之后,就会被移动到老年代。

新生代中的对象大都是朝生息死,一般都活不到一两次Monitor GC,而老年代中的对象能熬过那么多次GC,大多能存活很久。

所以针对新生代和老年代需要使用不同的收集算法来实现。

2、复制算法的优化

上面说过复制算法很浪费内存,有一半的内存完全浪费掉了。

那么为什么空闲的部分需要和使用部分的内存完全一致呢?是否可以考虑缩小空闲部分的内存大小呢?

如果我们将两块内存大小分配为6:4,此时占六成的内存用完了,需要执行一次复制算法清除”死亡”的对象,如果内存中的对象都是”存活”的状态,那么将大内存中的对象复制到小内存中的时候就会溢出。所以复制算法如果不按照5:5来分割内存可能会导致内存不足的问题。

所以如果内存中的对象不那么容易”死亡”的话,使用复制算法就只能使用5:5的内存分配,很浪费内存。而如果内存中的对象大都是朝生息死的话,就可以使用复制算法来进行垃圾收集了。

这里针对于内存中数据朝生息死的情况,可以再把复制算法优化一下。

我们将内存按照8:1:1的内存配比分为三块,一块Eden和两块Survivor。

我们将新对象存在Eden上,此时还有一块Survivor(暂时叫From Survivor)上存储了上次复制算法中”存活”的对象,当Eden内存满了之后使用复制算法将Eden和From Survivor内存上的对象复制到另一块Survivor(暂时叫To Survivor)上,由于内存中的对象大多是朝生息死的,所以一般情况下To Survivor是能够存储Eden + From Survivor中”存活”的对象的。如果To Survivor存放不了Eden + From Survivor中”存活”的对象,那么将借助其他内存进行分配担保。

复制算法经过这样的优化之后,对于内存的使用率将接近达到90%,并且在对象大都是朝生息死的情况下,10%的一块Survivor内存完全能存储的下90%内存中”存活”的对象。

3、新生代垃圾收集

由于新生代中对象大都是朝生息死,每次GC都会有大量的对象被清除,并且可以借助老年代的部分内存作用分配担保,所以上面内存按8:1:1划分的复制算法比较适合用在新生代垃圾收集上。

4、老年代垃圾收集

老年代对象由于存活率高,并且没有内存可作为分配担保,所以老年代可以使用标记-清除和标记-整理算法来进行垃圾回收。


喜欢这篇文章的朋友,欢迎扫描下图关注公众号lebronchen,第一时间收到更新内容。
这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值