事实上,即使被可达性分析算法判断为不可达,对象也不是“非死不可”,对象会先进入“缓刑”状态。要真正宣告一个对象死亡,至少要经历两次标记过程:
如果进行可达性分析后发现不存在任何从GC Roots到达对象的引用链,那么对象会被第一次标记并且进行进一步的筛选,筛选的条件是:对象是否有必要执行finalize()方法。若对象没有覆盖finalize()方法,或finalize()方法已经被虚拟机调用过,虚拟机认为对象没有必要执行finalize方法。
if(!可达性分析(对象)){ if(finalize方法执行必要性分析(对象)){ 将对象加入F-Queue队列; }else{ 回收; } }
boolean 可达性分析(对象){ return 存在从GC Roots到对象的引用链 ? true : false; }
boolean finalize方法执行必要性分析(对象){ return (对象覆盖了finalize方法 && finalize方法尚未被虚拟机调用) ? true : false; }
如果对象被判定为“需要执行finalize()方法”,对象会被加入F-Queue队列。稍后一个由虚拟机自动创建的、低优先级的Finalizer线程将会逐个执行F-Queue队列中各个对象的finalize()方法。
需要注意,这里说的执行,指的是虚拟机会触发这个方法,但并不承诺会等待方法执行结束。这样做是为了防止某个对象的finalize()方法执行缓慢(甚至出现死循环),影响F-Queue队列中其他对象的finalize()方法的执行(甚至导致整个内存回收机制奔溃)。
finalize()方法是对象逃脱“死刑”的最后一次机会。GC将对F-Queue中的对象进行第二次标记,如果对象在finalize()方法中成功拯救自己——只要重新与引用链上任何一个对象建立关联即可,譬如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那么在第二次标记时对象将被移出“死刑”名单;如果对象没有把握最后一次机会,那基本上它就要真的被“执行死刑”了。
下面来看一段代码:
public class FinalizeEscapeGC {
public static FinalizeEscapeGC SAVE_HOOK = null;
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize method executed!");
//自我拯救
FinalizeEscapeGC.SAVE_HOOK = this;
}
public static void main(String[] args) throws Exception{
SAVE_HOOK = new FinalizeEscapeGC();
SAVE_HOOK = null;
System.gc();
//因为finalize方法优先级很低,所以暂停0.5秒等待它
Thread.sleep(500);
if (SAVE_HOOK!=null){
System.out.println("yes, i am still alive...A");
}else {
System.out.println("no, i am dead...A");
}
SAVE_HOOK = null;
System.gc();
//因为finalize方法优先级很低,所以暂停0.5秒等待它
Thread.sleep(500);
if (SAVE_HOOK!=null){
System.out.println("yes, i am still alive...B");
}else {
System.out.println("no, i am dead...B");
}
}
}
main方法中,有两段几乎相同的代码,代码执行结果如下:
finalize method executed!
yes, i am still alive...A
no, i am dead...B
Process finished with exit code 0
第一段代码表明,对象成功结束finalize方法“逃脱死刑”;第二段代码表明,finalize方法并没有再次被调用。事实上,任何对象的finalize方法都只会被系统调用一次。
其实最好不要使用finalize方法,finalize方法不是C++里面的析构函数!finalize是Java诞生之初为了使C/C++程序员更容易接收它而做出的一个妥协。它的运行代价高昂,不确定性大,无法保证各个对象的调用顺序。finalize能做的所有工作,使用try-finally或者其他方式都可以做得更好、更及时。
《深入理解Java虚拟机》学习笔记
原文:https://www.cnblogs.com/KenBaiCaiDeMiao/p/12884565.html