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日志咯