【第五篇】深入学习Java虚拟机之垃圾收集算法

2018-11-28  本文已影响0人  秋慕云

第四篇内容,我们分享了如何判定一个对象是否存活,以及对象的二次逃脱,本节就在上一篇的基础上,讲解内存的回收算法。

回收算法

1. 标记——清楚算法

算法思路:
分为“标记”和“清除”两个阶段:首先标记处所有需要回收的对象,在标记万恒后统一回收被标记的对象

缺点:
a. 效率低
b. 会产生大量内存碎片

标记--清除算法示意图

2、复制算法

算法思路:
它将可用内存按容量划分为大小相等的两块,每次只用其中一块,当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已经使用过的内存空间一次性清理掉。

这样每次只需要对整个半区进行内存回收,内存分配时也不需要考虑内存碎片等复杂情况,只需要移动堆顶指针,按照顺序分配即可。复制算法的执行过程如图:

复制算法示意图

缺点:
a. 效率也比较低,比如在对象存活率较高的场景下要进行大量的复制操作,当然如果极端情况,比如对象100%存活的情况下,还需要额外的空间进行分配担保
b. 耗费内存空间

3、标记-整理算法

算法思路:
根据老年代的特点,有人提出了另外一种标记-整理算法,过程与标记-清除算法一样,不过不是直接对可回收对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉边界以外的内存。标记-整理算法的工作过程如图:

标记整理算法示意图

4、分代收集算法

算法思路:
作为现代商用虚拟机基本都采用的“算法”,与其称之为一种算法,不如说是上面三种算法的一种组合。即,Java堆一般分为新生代和老年代,根据各个年代的特点,分别采用上面三种算法的某一种来进行垃圾回收

比如,在新生代中,每次垃圾回收都发现有大量的对象死去,只有少量存活,这种情况,采用复制算法效果会更好一点,只需要复制少量存活的对象就可以完成收集。

而老年代中,因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记——清除”或“标记——整理”算法来进行回收。
堆内存布局如下图所示:

分代收集算法示意图
上一篇下一篇

猜你喜欢

热点阅读