1、标记清除算法
分为2个阶段:
1、标记阶段:使用可达性分析算法,从GC ROOT通过引用链遍历出所有存活对象
2、清除阶段:从内存中删除没有被标记的对象 也就是非存活对象
优点:实现简单 只需要一阶段给每个对象维护标志位,第二阶段删除对象
缺点:
内存碎片化问题
分配速度慢
2、复制算法
1、准备to、from空间 每次在对象分配阶段只使用from空间
2、垃圾回收GC阶段,from中存活的对象复制到to空间
3、from、to空间互换
完整例子:
1、from里:A、B、C、GC ROOT对象 GC ROOT对象关联B、C
2、GC阶段开始 GC Root以及关联的对象搬运到TO
3、交换
优点:
吞吐量高——比标记清除算法少了一次遍历过程(但是性能比不过 因为要移动对象)
不会发生内存碎片化
缺点:内存使用效率低——只能使用一般的空间 另一半用来gc
3、标记整理算法
对标记清除算法中容易产生内存碎片问题的解决方案
1、标记阶段:使用可达性分析算法,从GC ROOT通过引用链遍历出所有存活对象(与标记清楚的标记阶段一样)
2、整理阶段:将存货的对象移动到堆的一段,清理掉非存活对象的内存空间(这样就不会产生内存碎片了)
优点:
内存使用效率高(整个堆都可以使用,不像复制算法只能使用半个堆内存)
不会发生碎片化
缺点:整理阶段的效率不高
4、分代GC算法
现代最优秀的垃圾回收算法 将上述算法组合进行使用
将内存区域划分为
1、年轻代(新生代) :存放存活时间较短的对象 (分为 伊甸园区eden 幸存者区S0From、S1To)
2、老年代 :存放存活时间较长的对象
Minor GC —— 年轻代GC
伊甸园区对象越来越多 满了之后 出发年轻代GC(Minor GC 或 Young GC)
年轻代GC会把伊甸园区中和From需要的对象回收 然后把没有回收的对象放入To区
接下来to和from区会互换(类似复制算法)
特殊情况:幸存者区内存不够时 会将对象移动到老年代 不用等晋升
晋升
每次MinorGC都会为对象记录年龄,初始为0,每次GC+1 当年龄到达阈值(最大15 默认值与垃圾回收器有关),对象就会被晋升到老年代
Full GC —— 老年代GC
老年代空间不足无法放入新的对象,先尝试minor gc,如果还是不足,就会触发full gc,full gc会对整个堆进行垃圾回收
Out of Memory异常
如果full gc依然无法回收掉老年代的对象,那么当对象继续放入老年代时,就会抛出此异常
分代GC将堆分为新生代和老年代的主要原因:
1、通过调整新生代和老年代的臂力来适应不同场景,提高内存利用率和性能
2、新生代、老年代使用不同的垃圾回收算法,新生代一般使用复制算法,老年代可以选择标记清除、标记整理算法 由程序员选择灵活度较高