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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章