垃圾回收算法
- 标记-清除算法 该算法分为两个阶段:标记和清除,首先标记出所有需要回收的对象,在标记完成之后,统一回收所有被标记的对象。 不足之处:一是效率问题,标记和清除两个过程的效率都不高;二是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后再程序中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾回收动作。
- 复制算法 复制算法将内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块内存用完,就将还存活的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。这样,每次回收只是针对整个半区,且不会产生内存碎片问题。 该算法实现简单,运行高效,但代价是将内存缩小了一半。 现在商业虚拟机均采用该算法对新生代进行回收,但并不按照1:1的比例划分内存。而是将内存分为一块较大的Eden空间和两块较小的Survivor空间。每次使用Eden空间和其中一块Survivor空间。当回收时,将Eden空间和Survivor空间中还存活的对象复制到另一块Survivor空间中,最后清理掉Eden空间和之前用过的Survivor空间。(适用于对象存活率较低的场景) HotSpot中默认
Eden:Survivor:Survivor = 8:1:1。 如果在回收时,有大于10%时的对象都存活,即预留的Survivor空间不够用,就要依赖其他内存(老年代)进行分配担保:直接进入老年代。
- 标记-整理算法 针对老年代的一种算法。该算法在标记阶段与标记-清除算法一致,但后续并不对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
- 分代收集算法 顾名思义,根据对象的存活周期的不同将内存划分为几块,一般是将堆分为新生代和老年代,然后根据各个年代的特点采用最适当的收集算法。 在新生代,每次垃圾回收时都发现有大批对象死去,只有少量存活,就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。 在老年代,由于对象存活率高、没有额外空间对它进行分配担保,就必须使用标记-清除或者标记-整理算法进行回收。