GC对象的判定和GC算法

来源:互联网 发布:网络诈骗手段方式 编辑:程序博客网 时间:2024/05/21 18:36

一 GC对象的判定

1 引用计数算法

       对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1。只要对象A的引用计数器的值为0,则对象A就不可能再被使用。主要缺点是很难解决对象之间相互循环引用的问题

从图1右边可以看出,当根对象Root Obj不再引用Obj1时,由于Obj1,Obj2和Obj3三者之间存在循环引用,所以引用计数不为0,即被判定为不能回收。










2 可达性分析算法

       目前主流虚拟机判定对象是否存活是采用可达性分析算法。其基本原理是通过一系列被才能为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Root 没有任何引用链,则可判定位能被回收对象。

从图二可以看出,对象Obj1, Obj2 ,Obj3 和Obj4都存在到GC Root得引用链,而此不会给GC。相反,虽然Obj5, Obj6 ,Obj7三者之间存在循环引用,但是它们到GC Root是不可达的,因此会被判定位可回收对象。



二 GC算法

1 标记-清除算法

       分为“标记”和“清除”两个阶段。在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。

主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高;另外一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。


2 复制算法

       将原有的内存空间分为两块,每次只使用其中一块。在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。这种方法的优点是回收效率高,缺点是浪费内存

目前HotSpot虚拟机将内存分配为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和其中一块Survivor。发生GC时,将Eden和Survivor中还存活的对象一次性地复制到另外一块Survivor空间上,最后清理掉Eden和刚才使用过的Survivor空间。因为Eden和2块Survivor的大小比例为8:1:1,只有10%的内存会被浪费,所以且不适合老年代较多的对象


3 标记-整理算法

       首先需要从根节点开始,对所有可达对象做一次标记。但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。适合老年对象比较多的场景


4 分代收集算法

       目前主流的GC回收算法。根据对象的存活周期进行分类,把Java堆中短命的对象归为新生代,长命的对象归为老年代。根据不同代的特点,选取合适的收集算法 。新生代中对象存活较少,采用复制算法;老年代中有大量的对象存活,采用标记-清理或者标记-整理算法。

 

 

三 参考文献

 [1].周志明, 深入理解Java虚拟机:JVM高级特性与最佳实践. 2 . 2015:机械工业出版社.