垃圾回收的基本思想是考察每個對象的可觸及性,即從根節點開始是否能夠訪問到這個對象,若是能夠,則說明當前對象正在被使用,若是從全部的根節點都沒法訪問到某個對象,說明該對象已經再也不使用了,通常來講,此對象符合垃圾回收的條件。可是,一個沒法觸及的對象有可能在某個條件下復活本身,若是這樣,那麼對它的回收就是不合理的,爲此,須要給出一個可觸及性狀態的定義,並規定在什麼狀態下,才能夠安全的回收對象。安全
可觸及的包括3種狀態:jvm
以上3種狀態,只有在對象不可觸及時才能夠被回收。ide
1 對象的復活函數
實例1 :前面提到,對象可能在finalize()函數中復活本身,這裏給出一個實例。this
package com.jvm;
public class CanReliveObj {
public static CanReliveObj obj ;
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("CanReliveObj finalize called");
obj = this;
}
@Override
public String toString() {
return "CanReliveObj";
}
public static void main(String[] args) throws InterruptedException {
obj = new CanReliveObj();
obj = null;
System.gc();
Thread.sleep(1000);
if(obj==null){
System.out.println("obj is null");
}else{
System.out.println("obj 可用");
}
System.out.println("第二次GC");
obj = null;
System.gc();
Thread.sleep(1000);
if(obj==null){
System.out.println("obj is null");
}else{
System.out.println("obj 可用");
}
}
}對象
運行代碼打印:資源
CanReliveObj finalize called
obj 可用
第二次GC
obj is nullio
能夠看出,在第一次將obj置爲null後,進行GC,結果發現obj對象被複活了。等到第二次再釋放對象引用並運行GC,對象才真正被回收。這是由於第一次GC時,在finalize()函數調用以前,雖然系統中的引用已經被清除,可是在實例方法finalize()中,對象的引用this依然被傳入方法內部,致使引用外泄,對象復活,此時對象又變成可觸及狀態。因爲finalize()函數只會被調用一次,所以,在第二次清除釋放對象的引用時,對象就再無機會復活,所以會被回收。class
注意:垃圾回收
finalize()函數是一個糟糕的應用模式,不推薦使用finalize()函數釋放資源。
由於:其一,finalize()函數有可能發生引用外泄,在無心間復活對象
其二,因爲finalize()是被系統調用的,調用時間是不明確的,所以不是一個好的資源釋放方案,推薦使用try-catch-finally語句進行資源的釋放。