标记-清楚算法
- 最基础的收集算法,分为“标记”和“清除”两个阶段。它有两个不足的地方:一个是效率问题,标记和清除这两步的效率都不高,第二个是空间问题,标记清除之后会产生大量不连续的内存碎片,导致要分配较大的内存空间时无法找到连续的内存而导致触发另一次的垃圾回收动作。标记-----清除算法的执行动作,如下图:
复制算法
- 为了解决效率的问题,复制算法出现了。它将内存按容量分为大小相等的两块,每次只使用一块,当这一块的内存用完的时候,将还存活的对象复制到另一块上,然后清空自己。这样每次都是对整个半区进行内存回收,内存分配不需要考虑内存碎片的复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。只是这种算法的代价是缩小内存为原来的一般,你说是不是很伤!!!
- 复制算法在较多对象存活的时候要经行较多的复制操作,效率就会变低。而且又浪费了百分之五十的内存空间,不适用于老年代,赋值算法的执行示意图如下:
标记整理算法
- 根据老年代的特点,有人提出了标记整理的算法,标记过程与标记清除的一致,但是后续的操作变为将活的内存向一端移动,然后直接清理掉边界以外的内存。标记整理算法的示意图如下:
分代收集算法
- 分代收集算法只是将存活周期的不同,将内存划为几块。一般将Java堆分为新生代和老年代,根据各个年代的特点采取合适的收集算法。在新生代中,每次垃圾收集的时候对象都大批量的死去,所以采用复制算法,只需要完成少量存活对象的复制就可以完成收集。老年代因为对象存活率比较高,所以采用标记清除或者标记整理算法来实现。