标记-清除算法示意图
- 标记-清除算法是最基础的垃圾收集算法。
- 算法分为两个阶段,标记和清除。
- 首先标记出需要回收的对象,标记完成后,统一回收掉被标记的对象。
- 当然可以反过来,先标记存活的对象,统一回收未被标记的对象。
- 标记-清除 两个缺点是,执行效率不稳定和内存空间的碎片化问题
标记-复制算法示意图
- 1969年 Fenichel提出“半区复制”,将内存容量划分对等两块,每次只使用一块。当这一块内存用完,将还存活的对象复制到另外一块,然后把已使用过的内存空间一次清理掉
- 1989年,Andrew Appel提出“Appel式回收”,把新生代划分为较大的Eden和两块较小的Survivor空间。每次分配内存只使用Eden和其中一块Survivor空间。发生垃圾收集时,将Eden和Survivor中仍然存活的对象一次性复制到另外一块Survivor空间上。Eden和Survivor比例是8:1
- “半区复制”缺点是浪费可用空间,并且,如果对象存活率高的话,复制次数就会变多,效率也会降低
标记-整理算法示意图
- 1974年,Edward 提出“标记-整理”算法,标记过程跟“标记-清除”算法一样,接着让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存
- 标记-清除算法和标记整理算法本质差异是:前者是一种非移动式的回收算法,后者是移动式的回收算法。
- 是否移动存活对象都存在优缺点,移动虽然内存回收复杂,但是从程序吞吐量来看,更划算;不移动时内存分配更复杂,但是垃圾收集的停顿时间会更短,所以看收集器取舍问题~
- Parallel Scavenge收集器是基于标记-整理算法的,因为关注吞吐。CMS收集器是基于标记-清除算法的,因为它关注的是延迟。
垃圾收集器组合图
- 新生代收集器:Serial、ParNew、Parallel Scavenge
- 老年代收集器:CMS、Serial Old、Parallel Old
- 混合收集器:G1