java類中的成員成員變量賦值之后什么時(shí)候會(huì)被回收,有什么辦法監(jiān)聽到某一個(gè)對(duì)象被回收嗎
問(wèn)題描述
java類中的成員成員變量賦值之后什么時(shí)候會(huì)被回收,有什么辦法監(jiān)聽到某一個(gè)對(duì)象被回收嗎
問(wèn)題解答
回答1:一個(gè)對(duì)象是否被回收并不是僅僅靠當(dāng)前對(duì)象是否被引用這么簡(jiǎn)單粗暴的方法去判斷。
JVM中判斷是否回收一個(gè)對(duì)象使用的是可達(dá)性分析算法,GC ROOT不可到達(dá)的節(jié)點(diǎn)都將會(huì)被標(biāo)記上,一個(gè)對(duì)象如果被標(biāo)記了兩次就會(huì)被回收掉。至于這個(gè)可達(dá)性分析算法你可以自行百度一下,原理是很簡(jiǎn)單的。
那么用什么方法來(lái)監(jiān)聽一個(gè)對(duì)象是否被回收呢?當(dāng)然用fianlize了;
請(qǐng)看代碼:
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('要死了要死了要死了!'); } }
執(zhí)行結(jié)果:
要死了要死了要死了!null
那是不是執(zhí)行了finalize后,對(duì)象就一定會(huì)被回收呢?其實(shí)也不一定finalize調(diào)用時(shí)對(duì)象僅有一次拯救自己的機(jī)會(huì),如下:
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; } }
執(zhí)行結(jié)果如下:
要死了要死了要死了!com.Test@1aa9f99null
可以看到在第一次垃圾回收時(shí),在finalize方法給當(dāng)前回收對(duì)象賦值給了新的引用,避免了被回收,不過(guò)finalize方法一個(gè)對(duì)象只能調(diào)用一次,在第二次回收時(shí)將不會(huì)被調(diào)用了。
從上述兩個(gè)例子中我們可以得出:finalize可以監(jiān)聽一個(gè)對(duì)象被回收,但是不能保證調(diào)用了finalize的對(duì)象一定會(huì)被回收,同時(shí)一個(gè)對(duì)象在第二次標(biāo)記回收時(shí)是不會(huì)觸發(fā)finalize的!如果想絕對(duì)監(jiān)聽一個(gè)對(duì)象是否被回收,只有在JVM里面添加參數(shù)-XX:+PrintGCDetails分析GC日志咯
回答2:不一定什么時(shí)候。那個(gè)對(duì)象類的析構(gòu)函數(shù)不就可以么。
