JVM中判断对象是否存活的方法
2016-10-24 15:51
309 查看
Java中几乎所有的对象实例都存放在堆中,在垃圾收集器对堆内存进行回收前,第一件事情就是要确定哪些对象还“存活”,哪些对象已经“死去”(即不可能再通过任何途径被使用)。
什么是引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值加1;当引用失效时,计数器值减1.任何时刻计数器值为0的对象就是不可能再被使用的。那为什么主流的Java虚拟机里面都没有选用这种算法呢?其中最主要的原因是它很难解决对象之间相互循环引用的问题。在下面的代码中,我们在testGC()中new两个ReferenceCountingGC对象objA和objB,然后令objA.instance=objB,objB.instance=objA,最后令objA和objB都为null。此时,这两个对象实际上已经不可能再被访问,但由于它们互相引用着对方,导致它们的引用计数器值都不为0,于是使用引用计数算法无法通知GC收集器回收它们。
现在,我们在main方法中调用testGC(),然后打印GC日志(在Myeclipse中打印GC日志的方法)。得到结果为:
0.161: [GC 4761K->568K(124416K), 0.0022505 secs]
0.163: [Full GC 568K->471K(124416K), 0.0201927 secs]
由“4761K->568K”我们可以得知,虚拟机并没有因为这两个对象相互引用就不回收它们,这也从侧面说明了hotspot虚拟机并不是通过引用计数算法来判断对象是否存活的。
那么,在主流的商用程序语言的主流实现中,是通过什么方法来判断对象是否存活的呢?答案是下面将要介绍的可达性分析算法。
在Java语言中,可作为GC Roots的对象包括下面几种:
1. 虚拟机栈(栈帧中的本地变量表)中引用的对象;
2. 方法区中类静态属性引用的对象;
3. 方法区中常量引用的对象;
4. 本地方法栈中JNI(即一般说的Native方法)引用的对象。
引用计数算法
首先需要声明,至少主流的Java虚拟机里面都没有选用引用计数算法来管理内存。什么是引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值加1;当引用失效时,计数器值减1.任何时刻计数器值为0的对象就是不可能再被使用的。那为什么主流的Java虚拟机里面都没有选用这种算法呢?其中最主要的原因是它很难解决对象之间相互循环引用的问题。在下面的代码中,我们在testGC()中new两个ReferenceCountingGC对象objA和objB,然后令objA.instance=objB,objB.instance=objA,最后令objA和objB都为null。此时,这两个对象实际上已经不可能再被访问,但由于它们互相引用着对方,导致它们的引用计数器值都不为0,于是使用引用计数算法无法通知GC收集器回收它们。
public class ReferenceCountingGC { public Object instance = null; private static final int _1MB = 1024 * 1024; /** * 这个成员属性的唯一意义就是占点内存,以便在能在GC日志中看清楚是否有回收过 */ private byte[] bigSize = new byte[2 * _1MB]; public static void testGC() { ReferenceCountingGC objA = new ReferenceCountingGC(); ReferenceCountingGC objB = new ReferenceCountingGC(); objA.instance = objB; objB.instance = objA; objA = null; objB = null; // 假设在这行发生GC,objA和objB是否能被回收? System.gc(); } public static void main(String[] args) { testGC(); } }
现在,我们在main方法中调用testGC(),然后打印GC日志(在Myeclipse中打印GC日志的方法)。得到结果为:
0.161: [GC 4761K->568K(124416K), 0.0022505 secs]
0.163: [Full GC 568K->471K(124416K), 0.0201927 secs]
由“4761K->568K”我们可以得知,虚拟机并没有因为这两个对象相互引用就不回收它们,这也从侧面说明了hotspot虚拟机并不是通过引用计数算法来判断对象是否存活的。
那么,在主流的商用程序语言的主流实现中,是通过什么方法来判断对象是否存活的呢?答案是下面将要介绍的可达性分析算法。
可达性分析算法
可达性分析算法的基本思路是:通过一系列的称为“GC Roots”的对象作为起始点,从这些节点考试向下探索,搜索所走过的路径称为“引用链”,当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则证明此对象是不可用的。如下图中,对象object5、object6、object7虽然互有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。在Java语言中,可作为GC Roots的对象包括下面几种:
1. 虚拟机栈(栈帧中的本地变量表)中引用的对象;
2. 方法区中类静态属性引用的对象;
3. 方法区中常量引用的对象;
4. 本地方法栈中JNI(即一般说的Native方法)引用的对象。
相关文章推荐
- 判断Java对象是否存活的方法
- jvm判断对象是否存活
- 深入理解jvm虚拟机-判断对象是否存活
- 深入理解JVM--第三章--判断对象是否存活(引用计数算法、可达性分析算法,最终判定)
- 判断Java对象是否存活的方法
- HashSet 中储存先判断对象的hash值 如果一样 在调用 对象equals方法判断是否是同一个对象
- jQuery判断获得的对象是否存在的方法
- js中判断Object、Array、Function等引用类型对象是否相等的方法
- iphone上面判断一个对象是否是某个类的对象的方法
- 判断JavaScript对象是否存在的10个方法
- 快速判断JavaScript对象是否存在的十个方法
- 判断iframe或脚本对象是否加载完毕的方法(兼容ie和Firefox)
- 判断JavaScript对象是否可用的最正确方法分析
- javascript检测对象中是否存在某个属性判断方法小结
- javascript检测对象中是否存在某个属性判断方法小结
- VB.Net判断两个对象是否相同的方法
- 转判断JavaScript对象是否可用的正确方法
- freemarker判断对象是否为null方法
- (开发篇) null判断~ .net判断一个对象是否为空的方法(未完待续)
- jquery中判断对象是否可见的方法