谁才是真正的垃圾:判断对象的可触及性

垃圾回收的基本思想是考察每一个对象的可触及性,即从根节点开始是否可以访问到这个对象,如果可以,则说明当前对象正在被使用,如果从所有的根节点都无法访问到某个对象,说明该对象已经不再使用了,一般来说,此对象符合垃圾回收的条件。但是,一个无法触及的对象有可能在某个条件下复活自己,如果这样,那么对它的回收就是不合理的,为此,需要给出一个可触及性状态的定义,并规定在什么状态下,才可以安全的回收对象。

可触及的包括3种状态:

  • 可触及的:从根节点开始,可以到达这个对象;
  • 可复活的:对象的所有引用都被释放,但是对象有可能在finalize()函数中复活;
  • 不可触及的:对象的finalize()函数被调用,并且没有复活,那么就会进入不可触及状态,不可触及的对象不可能被复活,因为finalize()函数只会被调用一次。

以上3种状态,只有在对象不可触及时才可以被回收。

1 对象的复活

实例1 :前面提到,对象可能在finalize()函数中复活自己,这里给出一个实例。

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 null

可以看出,在第一次将obj置为null后,进行GC,结果发现obj对象被复活了。等到第二次再释放对象引用并运行GC,对象才真正被回收。这是因为第一次GC时,在finalize()函数调用之前,虽然系统中的引用已经被清除,但是在实例方法finalize()中,对象的引用this依然被传入方法内部,导致引用外泄,对象复活,此时对象又变成可触及状态。由于finalize()函数只会被调用一次,因此,在第二次清除释放对象的引用时,对象就再无机会复活,因此会被回收。

注意:

finalize()函数是一个糟糕的应用模式,不推荐使用finalize()函数释放资源。

因为:其一,finalize()函数有可能发生引用外泄,在无意间复活对象

        其二,由于finalize()是被系统调用的,调用时间是不明确的,因此不是一个好的资源释放方案,推荐使用try-catch-finally语句进行资源的释放。

 

转载于:https://www.cnblogs.com/zwbg/p/6197827.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值