标记—清除算法
标记—清除(Mark—Sweep)是最基础的收集算法。算法分为标记、清除两个阶段:
标记过程就是判定对象是否应该回收的过程。
这个算法有两个不足之处:
- 效率问题,标记和清除两个过程的效率都不高。
- 空间问题,标记清除之后会产生大量不连续的内存碎片,内存碎片太多可能会导致在分配较大对象时,无法找到足够的连续内存而提前触发GC。
清除前与清除后对比。
标记—复制(mark—copy)算法
标记复制算法将可用内存划分为大小相等的两块,每次只使用其中一块。当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过得内存空间一次清理掉。
如下图所示:
标记—清除—整理(mark—sweep-compact )算法
标记清除整理算法前面和标记清除算法一样,先标记后清除。在清除之后就是整理了,将所有存活的对象移动到一起。这样分配新的对象将会更加的容易。
如图所示:
分代收集(Generational Collection)算法
根据对象的存活周期不同将内存划分为几块,然后每块空间采用不同的收集算法。
Java堆分为新生代和老年代。
-
新生代
在新生代中,每次垃圾收集时都会有大批量对象死去,只有少量对象存活,所以新生代采用了标记复制算法。只需要复制出少量存活对象的成本就可以完成收集。
由于研究表明,新生代中 98% 的对象是朝生夕死的。所以并不需要按照1:1 的比例来划分内存空间。而是将内存划分为一块较大的 Eden 空间和两块较小的 Survivor 空间。HotSpot 虚拟机默 Eden 空间和 Survivor 空间比例是 8:1:1。 -
老年代
老年代中因为对象存活率高,所以采用标记清除整理算法来进行回收。
参考资料
1.Java Garbage Collection Algorithms [till Java 9]
2.Java Garbage Collection Basics
3.深入理解Java虚拟机