【Java面试】GC如何判断对象是否死亡

引用计数算法(不采用)

给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。

此方法是最简单的实现方法,但是无法解决对象相互循环引用的问题。
下面是一段伪代码。


Obj a = new Obj();// a = 1
Obj b = new Obj();// b = 1

a.instance = b;//b = 2
b.instance = a;//a = 2

a = null;// (a去掉Obj引用 - 1)a = 1
b = null;// (b去掉Obj引用 - 1)b = 1

// 垃圾回收
System.gc();

[GC (System.gc()) [PSYoungGen: 5248K->863K(76288K)] 5248K->871K(251392K), 0.0014251 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 863K->0K(76288K)] [ParOldGen: 8K->713K(175104K)] 871K->713K(251392K), [Metaspace: 3325K->3325K(1056768K)], 0.0081160 secs] [Times: user=0.11 sys=0.00, real=0.01 secs] 

我们知道,引用计数器的方式是没办法解决循环引用的情况,但是从GC日志中我们可以看出,还是被正确回收了,也就表明它并不是使用该方式。

这就引申出了一个新的知识,就是循环引用,我们来了解一下循环引用是如何出现的,和造成无法解决循环引用的原因。

循环引用1
我们把左下角这个对象当成A对象,右下角对象当成B对象。
这个图中,我们可以看到A对象被Java栈中的Obj1-reference引用,被Java堆中的B对象引用;B对象被Obj2-reference引用,被A对象引用。

那么我们摘除了A对象中Obj1-reference的引用,B对象Obj2-reference的引用,我们发现只剩下了。

循环引用2
我们把承接对象A的引用已经断开了,我们就无法再操作里面的对象内容了,我们无法把对象A中的ref对象置为null,如果使用了该算法的话,那就会导致了这两个在堆中的对象一直无法被垃圾回收清除了,因为计数器中的值永远不会降到0,除非我们手动去干预或者后续再去处理这种情况。
循环引用3
更加硬核一点的理解方法如图,当我们把直接p的指向去掉了,那么我们就无法再使用p这个指针对被原有指针p引用的对象进行操作了,所以这部分就只能通过其他手段去释放内存空间了。Java中我们没有办法手动去释放这些空间,当然Java也没有使用该算法作为垃圾回收标记的算法,他使用的是可达性分析算法。


可达性分析算法可达性分析算法

这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。

可作为GC Roots的对象

  • 虚拟机栈中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象

生存还是死亡

判断一个对象的生存还是死亡,在Java中,主要经过两次标记的过程,第一次经过可达性分析算法,判断是否GC Roots可达,如果不可达,则标记该对象“死缓”;第二次则判断是否重写finalize方法,如果重写该方法则把该对象加入F-Queue队列中,稍后由JVM虚拟中优先级比较低的线程Finalizer中执行该方法,并且该方法不等待执行的结果,因为这部分被重写的代码最坏情况可能导致队列的阻塞,GC在稍后就会对F-Queue中的对象进行二次标记,如果该对象没有在这个时间内被重新与GC Roots的对象产生关联,那么就会被标记为垃圾对象,宣判死亡。


总结

  1. 可达性分析算法标记GC Roots不可达对象;
  2. 判断是否重写finalize方法,没重写则宣判死亡;
  3. 如果重写,则加入F-Quene队列在finalizer线程中执行;
  4. 如果对象没有重新产生关联(再次可达性分析算法),则标记垃圾对象;
  5. GC处理垃圾对象。

参考资料

JVM垃圾回收对象判定标准之可达性分析算法(根搜索法)
JVM之GCRoots概述
引用计数法的循环引用问题
垃圾回收算法之引用计数算法
垃圾回收机制中,引用计数法是如何维护所有对象引用的?
《深入理解Java虚拟机:JVM高级特性与最佳实践》

文章中出现的任何错误欢迎指正!共同进步!

最后做个小小广告,有对WEB开发和网络安全感兴趣的,可以加群一起学习和交流!

交流群
QQ:425343603

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章