java类中的成员成员变量赋值之后什么时候会被回收,有什么办法监听到某一个对象被回收吗
阿神2017-04-18 10:52:02
一個物件是否被回收並不是僅僅靠當前物件是否被引用這麼簡單粗暴的方法去判斷。
JVM中判斷是否回收一個物件使用的是可達性分析演算法,GC ROOT不可到達的節點都將會被標記上,一個物件如果被標記了兩次就會被回收掉。至於這個可達性分析演算法你可以自行百度一下,原理是很簡單的。
那麼用什麼方法來監聽一個物件是否被回收呢?當然用fianlize了;
請看代碼:
public class Test {
private static Test TEST= null;
public static void main(String args[]) {
TEST = new Test();
TEST = null;
System.gc();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(TEST);
}
@Override
public void finalize() throws Throwable {
System.out.println("要死了要死了要死了!");
}
}
執行結果:
要死了要死了要死了!
null
那是不是執行了finalize後,物件就一定會被回收呢?其實不一定finalize呼叫時物件僅有一次拯救自己的機會,如下:
public class Test {
private static Test TEST= null;
public static void main(String args[]) {
TEST = new Test();
TEST = null;
System.gc();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(TEST);
TEST = null;
System.gc();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(TEST);
}
@Override
public void finalize() throws Throwable {
System.out.println("要死了要死了要死了!");
TEST = this;
}
}
執行結果如下:
要死了要死了要死了!
com.Test@1aa9f99
null
可以看到在第一次垃圾回收時,在finalize方法給了當前回收物件的新引用,避免了被回收,不過finalize方法一個物件只能呼叫一次,在第二次回收時將不會被調用了。
從上述兩個例子中我們可以得出:finalize可以監聽一個物件被回收,但是不能保證調用了finalize的物件一定會被回收,同時一個物件在第二次標記回收時是不會觸發finalize的!如果想絕對監聽一個物件是否被回收,只有在JVM裡面加入參數-XX:+PrintGCDetails分析GC日誌咯