标记清除(Mark Sweep)
将存活的对象进行标记,然后清理掉未被标记的对象。
优点:速度快
缺点:会产生大量不连续的内存碎片,导致无法给大对象分配内存。
标记整理(Mark Compact)
让所有存活的对象整理在一起,然后直接清理掉其他内存。
优点:没有内存碎片
缺点:速度慢
复制(Copy)
将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。
优点:没有内存碎片
缺点:需要双倍内存空间
现在的商业虚拟机都采用这种收集算法来回收新生代,每次使用 Eden 和其中一块 Survivor。在回收时,将 Eden 和 Survivor 中存活的对象一次性复制到另一块 Survivor 空间,最后清理 Eden 和使用过的那一块 Survivor。
HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了内存的利用率达到 90%。如果每次回收有多于 10% 的对象存活,那么一块 Survivor 空间就不够用了,此时需要依赖于老年代进行分配担保,也就是借用老年代的空间存储放不下的对象。
分代收集算法
一般将Java堆分为新生代和老年代,对应的收集算法不同。
-
在新生代中,划分一块较大的 Eden 空间和两块较小的 Survivor 空间。每次回收时都会发现大批对象死去,只有少量存活,因此新生代采用复制算法。
-
在老年代中,对象存活率高,并且没有额外空间进行分配担保。因此老年代使用标记-清除和标记-整理算法