JVM垃圾回收算法解析

四大回收算法

标记清除算法

思想:

  1. 标记过程:从GC root搜索,标记不可达对象
  2. 清除过程:清除标记的对象

缺点:产生内存碎片,若大对象进入,则会触发其他GC机制

标记整理算法

思想:

  1. 标记:从GC root搜索,标记不可达对象
  2. 整理:将存活对象整理到基地址开始位置挨个放置,将端边界外的内存清理掉

优点:没有内存碎片的产生问题
缺点:效率问题

复制算法

思想:

  1. 开辟两个容量相当的内存区,一个空闲(To区),一个装对象(From区)
  2. 标记:在From区中标记待回收对象
  3. 复制:将存活对象复制到To区,将From中残留的待回收对象清理掉,From->To,To->From

算法简单,运行高效,但有空间问题

分代算法

  1. 为了提升效率,JVM将堆区分为年轻代和老年代,默认占比1:2
  2. 年轻代又划分为Eden区和Survivor区,Survivor区分from和to区,默认Eden:from:to = 8:1:1
  3. 年轻代存放的是朝生夕死的对象,使用复制算法
  4. 老年代存放的是在年轻代中存活了设定期限的对象或者超过阈值的大对象,一般不容易不被使用,采用的是标记整理算法(或者标记清除算法)

比较

  1. 效率:复制算法>标记/整理算法>标记/清除算法(时间复杂度对比)
  2. 内存整齐度:复制算法=标记/整理算法>标记/清除算法。
  3. 内存利用率:标记/整理算法=标记/清除算法>复制算法

参考

上溯四种算法都是一搜一大把的,这篇文章的目的也不是简单的水一水,只是先把上述算法简单提一下,若要图文并茂可参考
Java JVM 8-java堆新生代,老年代的划分及回收算法
GC算法和种类【重要】
JVM内存管理------GC算法精解(复制算法与标记/整理算法)

问题

这才是本文的主要内容

标记的是待回收对象还是存活对象

两种观点

  1. 标记待回收对象
  2. 标记存活对象

个人粗浅认为,两种方法都可行,只是不同的实现,标记只是一个区分存活对象和待回收对象的方法,应该是具体看具体应用,考虑到各种算法的使用环境,个人还是倾向于标记整理/标记清除标记的是待回收对象,复制算法标记存活对象。标记是要耗时的,标记的应当是少数部分。
为什么JVM在标记-清除或标记-整理算法中,标记的是可回收对象,而不是存活对象一文中提到

在标记-清除或标记-整理过程中,假设有对象晋升到年老代,而此时在进行FULL GC的年老代处于已完成标记阶段工作但未完成清除阶段工作的状态。
那么如果一开始标记的是存活对象,在清除阶段工作开始后,就会意外地把刚晋升到年老代的对象给清除掉,为了避免这种意外性,JVM就设计成一开始就标记可回收对象(JVM年老代GC时,部分算法实现不是Stop The World)。
同时,在年老代中标记存活对象的耗时要比标记可回收对象的耗时要多得多。

但是有点疑惑full GC的时候是先尝试minor GC,且会有两种GC同时运行的情况吗。。
希望有大佬能回答一下

为什么年轻代使用复制算法

这个问题在面试的时候被问了好几次,下面的回答有引用上述参考文章

  1. 考虑复制算法的实现,把存活对象复制到空闲区域,多了空间浪费
  2. 从空间换时间的理论出发,既然使用了复制算法,那肯定是要从时间上得到回报的,复制算法的效率与内存方面都是前列的
  3. 复制这一工作所花费的时间,在对象存活率达到一定程度时,将会变的不可忽视
  4. 复制算法要想使用,最起码对象的存活率要非常低才行,而且最重要的是,我们必须要克服50%内存的浪费,这就很适合年轻代朝生夕死的特点了
  5. 标记/整理算法唯一的缺点就是效率也不高,不仅要标记所有存活对象,还要整理所有存活对象的引用地址。从效率上来说,标记/整理算法要低于复制算法
  6. 年轻代作为一个GC频繁的区域无疑是需要效率的

那么问题又来了,为什么标记整理效率不高呢

标记整理的过程到底是什么

我看深入理解java虚拟机意思大概为,标记整理是先标记,再将存活对象移动到一端进行整理,然后再清除回收对象,所以是标记-整理-清除,在整理这个部分需要考虑到是原地移动操作,所以耗时也能理解。

其余耗时:当移动一个对象的内存位置时, 需要让所有之前依赖这个对象的对象更新一下引用地址信息, 这样才不会在移动之后出错

但是为什么不能是标记-清除-整理呢,难道是因为清除非连续空间+移动耗时>整理移动的时候耗时+清除连续内存耗时

为什么非要等到标记全部结束才开始整理, 为什么不一边标记一边整理

原因在于对象的遍历过程和内存的摆放顺序不是一致的, 很可能一个对象摆放在内存的前面部分, 但是需要等到最后的时候才能遍历到这个对象, 因此, 如果提前开始整理, 会影响到这个对象

为什么标记清除比标记整理效率慢

标记整理不是有对象移动以及改变引用等耗时操作吗,标记清除都没有这个问题,那为什么会慢呢,难道又是清除非连续空间的耗时 >> 整理移动的时候耗时+清除连续内存耗时

我只是大自然的搬运工

上述问题,虽然提出来了,但是需要大佬解释一下,难顶

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值