finalize()分析

finalize()分析

PS : 本文乃学习整理参考而来 。


生存还是死亡:
        即使在可达性分析算法中不可达的对象也并非是“非死不可”的,这时候他们暂时处于“缓刑”阶段要真正确定一个对象死亡至少要经理两次标记过程:如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,则虚拟机将这两种情况都视为“没有必要执行”。如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会放置在一个叫做F-Queue的队列中,并在稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去执行它。这里所谓的“执行”是指虚拟机会触发这个方法但并不会承诺会等待它运行结束,这样做的原因是如果一个对象在finalize()方法中执行缓慢或者发生了死循环将可能会导致F-Queue队列中其他对象永久处于等待,甚至导致整个内存回收系统崩溃。finalize()方法时对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模标记,如果对象要在finalize()中成功拯救自己——只要重新与引用链上的任何一个对象建立关联关系即可,那在第二次标记时他将被移除出“即将回收”的集合如果这时候还没有逃脱,那基本上就真的被回收了。以下是finalized()案例

public class A{

    public static A  SAVE_HOOK = null;

    public void isAlive(){

        System.out.println("i am alive!);
    }

    @Override
    protected void finalize() throws Throwable {

        super.finalize();
        System.out.println("excuting finalize method!");
        SAVE_HOOK = this;

    }

    public static void main(String[] args){
        SAVE_HOOK = new A();
        //对象第一次成功拯救自己
        SAVE_HOOK = null;
        System.gc;
        //因为finalize方法优先级很低,所以暂停0.5秒等待它;
        Thread.sleep(500);

        if(SAVE_HOOK != null){
            SAVE_HOOK.isAlive();
        }else{
            System.out.println("no , i am dead!")
        }

        //对象第二次拯救自己,失败
        SAVE_HOOK = null;
        System.gc();
        Thread.sleep(500);
        if(SAVE_HOOK != null){
            SAVE_HOOK.isAlive();
        }else{
            System.out.println("no , i am dead!")
        }
    }
}
输出结果:  excuting finalize method!
         i am alive!
         no , i am dead!

从代码中可以看出SAVE_HOOK对象的finalize()方法确实被GC收集器触发过并且被收集前成果逃脱了。另外需要注意的是代码中有两段一样的片段,执行结果却只成功了一次,这是因为finalize()方法会被系统自动调用一次,如果面对已经执行过的对象进行新一次回收,他的finalize()方法不会再次被执行。书者建议尽量避免使用。

发布了41 篇原创文章 · 获赞 7 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章