Java中如何标记对象已经死亡

Java中如何标记对象已经死亡   

要真正宣告一个对象死亡,至少要经历两次标记过程。

  • 第一次标记
    在可达性分析后发现到GC Roots没有任何引用链相连时,被第一次标记;
    并且进行一次筛选:此对象是否必要执行finalize()方法;
  1. 没有必要执行
    没有必要执行的情况:

    • 对象没有覆盖finalize()方法;
    • finalize()方法已经被JVM调用过;
      这两种情况就可以认为对象已死,可以回收;
  2. 有必要执行
    对有必要执行finalize()方法的对象,被放入F-Queue队列中;稍后在JVM自动建立、低优先级的Finalizer线程(可能多个线程)中触发这个方法;

  • 第二次标记
    GC将对F-Queue队列中的对象进行第二次小规模标记;
    finalize()方法是对象逃脱死亡的最后一次机会:
    • 如果对象在其finalize()方法中重新与引用链上任何一个对象建立关联,第二次标记时会将其移出"即将回收"的集合;
    • 如果对象没有,也可以认为对象已死,可以回收了;
    • 一个对象的finalize()方法只会被系统自动调用一次,经过finalize()方法逃脱死亡的对象,第二次不会再调用;

这里有一段演示代码:

public class FinalizeEscapeGC {  
    public static FinalizeEscapeGC SAVE_HOOK = null;  

    public void isAlive() {  
        System.out.println("yes, I am still alive");  
    }  

    protected void finalize() throws Throwable {  
        super.finalize();  
        System.out.println("finalize method executed!");  
        FinalizeEscapeGC.SAVE_HOOK = this;  
    }  

    public static void main(String[] args) throws InterruptedException {  
        SAVE_HOOK = new FinalizeEscapeGC();  

        //对象第一次成功拯救自己  
        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 QAQ!");  
        }  

        //-----------------------  
        //以上代码与上面的完全相同,但这次自救却失败了!!!  
        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 QAQ!");  
        }  
    }  
}

你可能感兴趣的:(java)