垃圾回收的基本思想是考察每个对象的可触及性,即从根节点开始是否能够访问到这个对象,若是能够,则说明当前对象正在被使用,若是从全部的根节点都没法访问到某个对象,说明该对象已经再也不使用了,通常来讲,此对象符合垃圾回收的条件。可是,一个没法触及的对象有可能在某个条件下复活本身,若是这样,那么对它的回收就是不合理的,为此,须要给出一个可触及性状态的定义,并规定在什么状态下,才能够安全的回收对象。安全
可触及的包括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语句进行资源的释放。