垃圾收集算法
- 标记-清除算法
- 复制算法
- 标记-整理算法
- 分代收集算法
1. 标记-清除(Mark-Sweep)算法
- 最基础的垃圾收集算法,后续的收集算法都是基于这中思路并对其不足进行改进而得到的
- 算法分为"标记","清除"两个阶段,首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象
标记-清除算法的缺点
- 分配效率较低:如果是一块连续的内存空间,那么我们可以通过指针加法来做分配,而对于空闲列表,java虚拟机需要逐个访问列表中的项,来查找能够放入新建对象的空闲内存
- 空间问题:标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作
2. 复制算法
- 将可用的内存容量划分为大小相等的两块,每次只使用其中的一块
- 当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉
复制算法的优点
实现简单,运行高效
- 每次都是对整个半区进行内存回收,内分分配时也就不用考虑内存碎片化的情况
- 只要移动堆顶指针,按顺序分配内存即可
复制算法的缺点
- 内存缩小为了原来的一半
复制算法的使用场景
使用这种收集算法来回收新生代
3. 标记-整理算法
- 标记整理算法在标记-清除算法基础上做了改进
- 标记阶段是相同的标记出所有需要回收的对象
- 在标记完成后不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,在移动过程中清理掉可回收的对象,这个过程叫整理
标记-整理算法的优点
相比标记-清除算法:内存整理后不会产生大量不连续内存碎片问题
标记-整理算法的缺点
在对象存活率高的情况下就要执行较多的复制操作,效率将会变低,而在对象存活率高的情况下使用"标记-整理"算法效率会大大提高
4. 分代收集算法
- 此算法就是将上述三种算法整合了
- 根据对象存活周期的不同将内存划分为几块,一般是把java 堆,分为新生代和年老代,这样就可以根据各个年代的特点采取最适当的收集算法
- 在新生代中,每次垃圾手机时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集
- 而老年代中因为对象存活率高,没有额外空间对它进行分配担保,就必须使用 “标记-清除” 或者 “标记-整理” 算法来进行回收
现在的垃圾回收器往往会综合上述集中回收方式,综合它们的优点的同时规避它们的缺点
垃圾收集算法的应用:垃圾收集器可以说是垃圾收集算法的应用,可以看下一篇java虚拟机(三)垃圾收集器