判断对象已经死。不能通过引用计数算法,因为他无法解决对象之间相互循环引用的关系。如果两个对象彼此相互引用,但是在以后再也没用,那么岂不是浪费了空间,导致对象无法回收,通常是采用跟搜索算法,以一系列名为“GV Roots”的对象作为起始点,当一个对象到GC root没有任何引用链引用的时候,则表示这个对象可以被回收。可以作为GC root的对象有下面几种情况:
第一:虚拟机栈中引用的对象,也就是方法内部的局部变量引用的对象;
第二:方法区中类静态变量引用的对象;
第三:方法区中也就是类中全局常量引用的对象;
第四:本地方法引用的对象
代码测试:
public class FinalizeEscapeGC {
private static FinalizeEscapeGC SAVE_HOOD = null;
public void isAction(){
System.out.println("yes, i am is active");
}
@Override
protected void finalize() throws Throwable {
super.finalize();
Thread.sleep(5000);
// System.out.println("finalize is run !");
SAVE_HOOD = this;
}
public static void main(String[] args) {
SAVE_HOOD = new FinalizeEscapeGC();
//对象第一次拯救测试
SAVE_HOOD = null;
System.gc();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(SAVE_HOOD != null){
SAVE_HOOD.isAction();
}else{
System.out.println("no i am dead");
}
SAVE_HOOD = null;
System.gc();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(SAVE_HOOD != null){
SAVE_HOOD.isAction();
}else{
System.out.println("no i am dead");
}
/**
* 结果:
* finalize is run !
yes, i am is active
no i am dead
*/
/**
* 总结:
* 当java虚拟机通过跟搜索算法搜索对象是否可以被删除的时候,如果这个对象
* 到跟root没有任何的相连接的引用链,那么此时垃圾回收器并不会回收对象,他会
* 来判断当前对象是否有必要执行finalize方法,如果执行了,那么垃圾回收器再
* 回收之前会调用这个方法,如果在这个方法里面我们重新给这个对象链接引用连,
* 那么这个对象就会从垃圾回收器需要被回收的队列中移除,当然垃圾回收器不会
* 等到finalize方法执行完,在做决定,如果我们在finalize方法里面执行时间太长
* ,还没有给对象新的引用,这样垃圾回收器就有可能由于没有得到对象引用,而把对象
* 回收掉了。另外一点需要注意的是,一个线程,垃圾回收期只会调用一次finalize
* 方法,所以在第二次同样的代码情况下,却得到不同的结果,即对象被回收掉。
*/
}
}