java垃圾回收机制中,讲到GC判断可回收对象算法时,有一种可达性算法,不明白它如何解决对象循环引用问题的?
可达性算法可以分析出哪些对象在引用树上,那么剩下的对象就是可以回收的。如果是孤立的两个对象做循环引用,使用可达性算法分析后,这两个对象是不会在引用树上的,自然会把循环引用的两个对象判定为可回收的。循环引用问题是在另外一种标记计数的GC算法里才会有问题,这是一种比较古老的GC算法了,现代JVM已经不会采用这种方法了。
摘录周志明先生的《深入理解Java虚拟机》一书中对可达性算法的分析。
首先,可达性算法基本思路是定义一些列称为"GC-Roots"的对象作为起始阶段,从这些节点向下搜索,搜索走过的路径称为引用链,当一个对象到GCRoots没有任何引用链时(即从GCRoots到这个对象不可达),则证明此对象是不可用的。
其次,可达性算法中的不可达对象,在真正宣告“死亡”需要回收之前,至少要经过两轮标记过程:如果对象不可达,会被第一次标记并且进行一次筛选,筛选条件是次对象有没有必要执行finalize()方法。
当对象没有覆盖finalize()方法或者这个方法以及被执行过了,那么久视为没有必要再执行。
对于那些有必要执行finalize()方法的对象会被放在一个队列F-Queue中,然后稍后由虚拟机的一个线程去执行逐一执行队列中对象的finalize方法,如果线程在执行过程中发生了死循环,或者某个对象的finalize方法执行时间过长,导致队列其他对象一直处于等待,那么就会导致整个内存回收系统崩溃。
第三,finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC会对F-Queue中的对象进行第二次小规模的标记,如果能在finalize中成功重新引用,第二次标记时就会将该对象从F-Queue集合中移除,而成功脱逃。
所以,我理解你说的循环引用可能是想说不可达后突然又再次引用了,那么只能在finalize方法中再次引用而救活对象了。如果是普通循环中的循环操作引用,应该还没有涉及到垃圾回收、标记不可达的时候。
最后,算法中的根对象通常是全局的静态成员对象,方法区中的常量引用对象,Native引用对象,线程栈中的引用对象等。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。