GC判断可回收对象算法
声明:本文摘录周志明先生的《深入理解Java虚拟机》,记录下GC算法中的可达性算法分析。是在问答频道看到一个对可达性算法的疑问,梳理下,也是自我学习巩固的过程。关于可达性算法的几点记录如下:首先,可达性算法基本思路是定义一些列称为"GC-Roots"的对象作为起始阶段,从这些节点向下搜索,搜索走过的路径称为引用链,当一个对象到GCRoots没有任何引用链时(即从GCRoots到这个对象不可达
·
声明:本文摘录周志明先生的《深入理解Java虚拟机》,记录下GC算法中的可达性算法分析。是在问答频道看到一个对可达性算法的疑问,梳理下,也是自我学习巩固的过程。关于可达性算法的几点记录如下:
首先,可达性算法基本思路是定义一些列称为"GC-Roots"的对象作为起始阶段,从这些节点向下搜索,搜索走过的路径称为引用链,当一个对象到GCRoots没有任何引用链时(即从GCRoots到这个对象不可达),则证明此对象是不可用的。
其次,可达性算法中的不可达对象,在真正宣告“死亡”需要回收之前,至少要经过两轮标记过程:如果对象不可达,会被第一次标记并且进行一次筛选,筛选条件是此对象有没有必要执行finalize()方法。当对象没有覆盖finalize()方法或者这个方法以及被执行过了,那么就视为没有必要再执行。
对于那些有必要执行finalize()方法的对象会被放在一个队列F-Queue中,稍后由虚拟机的一个线程去执行逐一执行队列中对象的finalize方法,如果线程在执行过程中发生了死循环,或者某个对象的finalize方法执行时间过长,导致队列中其他对象一直处于等待,那么就会导致整个内存回收系统崩溃。
第三,finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC会对F-Queue中的对象进行第二次小规模的标记,如果能在finalize中成功重新引用,第二次标记时就会将该对象从F-Queue集合中移除,而成功脱逃。
所以,我理解的循环引用可能是想说不可达后突然又再次引用了,那么只能在finalize方法中再次引用而救活对象了。如果是普通循环中的循环操作引用,应该还没有涉及到垃圾回收、标记不可达的时候。
最后,算法中的根对象通常是全局的静态成员对象,方法区中的常量引用对象,Native引用对象,线程栈中的引用对象等。
附上一个可达性算法中笫二次标记自我复活的例子:
/**
* 自我救赎的机会只有一次,即重新finalize并再次引用自己,
* 因为一个对象的 finalize()方法最多只会被系统调用一次
*
*/
public class FinalizeEscapeGC {
public static FinalizeEscapeGC save_hook = null;
public void isAlive() {
System.out.println("yes ,I am still alive.");
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize method executd!");
FinalizeEscapeGC.save_hook = this;
}
public static void main(String[] args) throws Throwable {
save_hook = new FinalizeEscapeGC();
// 设置为null,标记不可达,通知GC回收
save_hook = null;
System.gc();
// 当前线程休眠5秒,让GC线程优先执行
Thread.sleep(500);
if (save_hook != null) {
//finalize()中自引用成功,该分支执行了
save_hook.isAlive();
} else {
System.out.println("first .Oh My God ,I am going to dead.Who can help me?");
}
// 再测试一次:下面代码与上面完全相同,但是自我救赎失败,因为finalize只会执行一次
save_hook = null;
System.gc();
// 当前线程休眠5秒,让GC线程优先执行
Thread.sleep(500);
if (save_hook != null) {
save_hook.isAlive();
} else {
//已经执行过finalize()了,不能再逃脱回收命运了
System.out.println("second Oh My God ,I am going to dead.Who can help me?");
}
}
}
测试结果可以看到对象能够完成一次在finalize中的自我复活,但是也仅有这一次机会,最终还是逃不脱GC的命运。
更多推荐
已为社区贡献13条内容
所有评论(0)