一般情况任务虚拟机GC回收内存中的不可达对象,但是这是不完全对的,因为在内存中的对象有一部分不可达的对象也是不可以被回收的,这些对象就是 可复活对象。
引入一个概念就是可触及。
可触及的对象,为从root也就是根节点可以触及到这个对象。这个对象就是可触及对象。一般的理解GC就是销毁不可触及的对象。
而还有一类对象是不可触及的但是不能被GC回收 ,这些对象就是可复活对象。那么什么是可复活对象呢?
一旦所有引用被释放这个对象就会变成可复活状态,那么这个对象就是可复活对象。why?
由下面这张图可以看到在java中的所有类的超类object 有一个finalize方法。
就是这个方法可以把被释放的对象重新复活。如果一个对象被释放之后 可能被复活那么这个对象就不能被GC干掉。
那么岂不是所有的对象都不能被干掉了?肯定不是的,不然jvm内存早就爆炸了,就是在finalize执行之前这个对象是可复活对象,但是finalize一旦执行之后 这个对象就变成了不可复活对象,只能等着GC干掉。
在这里做一点总结:
GC干掉的不是不可达 或者说是不可触及的对象,而是干掉不可复活的不可触及的对象。
下面做一个代码demo:
package realive;
public class CanReliveObj {
public static CanReliveObj obj;
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("canrelive obj finalize obj");
obj = this;
}
@Override
public String toString(){
return "i am canreliveobj";
}
public static void main(String[] args) throws InterruptedException {
obj = new CanReliveObj();
obj=null;
System.out.println("第一次gc");
System.gc();
Thread.sleep(1000);
if(obj == null){
System.out.println("obj 是 null");
}else {
System.out.println("obj 可用");
}
System.out.println("第二次gc");
obj=null;
System.gc();
Thread.sleep(1000);
if(obj==null){
System.out.println("obj 是 null");
}else {
System.out.println("obj well");
}
}
}
执行结果:
第一次gc
canrelive obj finalize obj
obj 可用
第二次gc
obj 是 null
由上面的结果可以看出GC在finalize之后就不能再复活了。因为(打印了canrelive obj finalize obj 证明finalize被执行,引用被释放,状态变为不可复活状态)对象在第二次gc的时候被干掉了。
我们再这里只是对finalize进行试验,其实在obj被复活之后,如果不进行obj=null
操作obj可能永远不会被回收 。
下面简单介绍一下finalize
1、避免使用finalize(),操作不慎会导致错误
2、优先级低,合适被调用不确定(何时GC也不确定)
3、可以使用try-catch-finally
来代替