1. 标记-清除算法
标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象,未被标记的对象便是未被引用的垃圾对象。在清除阶段,清除所有未被标记的对象。
缺点:
- 效率低,标记和清除两个阶段的效率都不高。
- 空间问题,标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大的对象时,无法找到足够的连续空间而不得不提前出发另一次垃圾收集动作。
2. 标记-整理算法
标记整理算法类似于标记清除算法,不过该方法是标记完对象之后,不是直接对可回收的对象进行清除,而是让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存。
优点:
- 相对标记-清除算法,解决了内存碎片问题
- 没有了内存碎片问题,对象创建分配内存更快速
缺点:
- 效率低,标记和整理两个阶段的效率都不高。
3. 复制算法
复制算法,将可用内存容量划分为大小相等的两块,每次只使用其中的一块,当这一块用完了,就将还存活着的对象复制到另一块上面,然后再把已经使用过的内存空间一次清理掉,这样使得每次都是对整个半区进行内存回收,内存分配时也就不用内存碎片问题,只要移动堆顶指针,按顺序分配内存即可。
优点:
- 效率高,没有内存碎片
缺点:
- 浪费一半的内存空间。
- 复制算法在对象存活率较高时就要进行较多的复制操作,效率将会变低。
4. 分代收集算法
分代收集算法,根据对象存活周期的不同将内存划分为若干块,一般是把Java堆分为新生代和老年代,然后根据各个年代的特点采用最适当的收集算法,在新生代中,每次垃圾收集都发现有大批量对象死去,只有少量对象存活,选用复制算法。然而老年代中,因为对象的存活率高,没有额外空间对它进行分配担保,就必须使用“标记清理”或“标记整理”算法来进行回收。