1.标记清除算法
标记清除算法(Mark-Sweep)分为标记和清除两个阶段,先标记出要回收的对象,然后统一回收这些对象。
优点:简单
缺点:效率不高,标记和清除的效率都不高。同时标记清除后会产生大量不连续的内存碎片,从而导致在分配对象时触发GC
2.复制算法
复制算法(Copying)把内存分成两块完全相同的区域,每次使用其中一块;当一块用完了,就把这块上还存活的对象拷贝到另外一块,然后把这块清除掉。
优点:实现简单,运行高效,不用考虑内存碎片问题。
缺点:内存有些浪费。
ps:JVM实际实现中,是将内存分成一块较大的Eden区和两块较小的Survivor,每次使用Eden和一块Survivor,回收时把存活的对象复制到另外一块Survivor。Hotspot默认的Eden和Survivor空间比是8:1,即每次能用90%的新生代空间;如果回收时的一块Survivor空间不够,就要依赖老年代进行分配担保,把放不下的对象直接放入老年代。
3.标记整理法
背景:由于复制算法在存活对象比较多的时候效率较低,且空间有浪费,因此老年代一般不会选择复制算法,老年代多选用标记整理算法。
标记整理法(Mark-Compact)标记过程与标记清除一样,但后续不是直接清除可回收对象,而是将所有存活对象都向一端移动,然后直接清除边界以外的内存。
注1:分配担保
当新生代进行垃圾回收后,新生代的存活区放置不下存活的对象,就需要把这些对象放置到老年代中,即老年代要为新生代的GC做空间分配担保,具体步骤如下:
1.在MinorGC之前,JVM会检查老年代的最大可用连续空间是否大于此时新生代所有对象的总空间,如果大于则可以确保MinorGC是安全的。(最坏情况下老年代依然能够放得下)
2.如果小于,那么JVM会检查是否设置了允许担保失败,如果允许,则会继续检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小。(考虑平均情况,概率问题,差不多就可以)
3.如果大于,则尝试进行一次MinorGC。
4.如果小于,则进行一次Full GC。