Java垃圾回收--判断可触及性

博客搬家自https://my.oschina.net/itsyizu/blog/

垃圾回收的基本思想:

考察每一个对象的可触及性(从根节点开始是否可以访问到这个对象,如果可以,这说明当前对象正在使用,否则,说明这个对象已经不再使用了),一般来说,这个对象就需要被回收了。

但事实上,一个无法触及的对象可以在一定的条件下复活自己,如果是这样,那么对它的回收就是不合理的,为此,需要给出一个对象可以触及性状态的定义。

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

代码来帮忙

下面给出一个例子,该对象在finalize中复活了

public class CanReliveObj {
    public static CanReliveObj obj;
    public void finalize()
    {
    try {
        super.finalize();
    } catch (Throwable ex) {
        // TODO Auto-generated catch block
        ex.printStackTrace();
    }
    System.out.println("CanReliveObj finalize called");
    obj=this;
    }
    public String toString()
    {
    return "I am CanReliveObj";
    }
    public static void main(String [] args)
    {
    obj=new CanReliveObj();
    obj=null;
    System.gc();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ex) {
        // TODO Auto-generated catch block
        ex.printStackTrace();
    }
    if(obj==null)
    {
        System.out.println("obj is null");
    }else
    {
        System.err.println("you can  use obj");
    }
    System.err.println("第二次gc");
    obj=null;
    System.gc();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ex) {
        // TODO Auto-generated catch block
        ex.printStackTrace();
    }
    if(obj==null)
    {
        System.out.println("obj is null");
    }else
    {
        System.err.println("you can  use obj");
    }

    }
}

image

第一次对该对象清理会调用它的finalize函数,虽然系统中的引用已经被清除,但是作为实例方法finalize,对象的this引用依然会被传入方法内部,如果引用外泄,对象就会复活。而finalize函数只会调用一侧,所以,第二次清楚对象的时候,对象就没有机会再复活。

NOTICE

finalize函数是一个非常糟糕的模式,不推荐大家使用finalize函数来释放资源。

因为:
>

  • finalize函数有可能发生引用外泄,在无意中复活对象.
  • 由于finalize是被系统调用的,调用的时间不明确,因此不是一个很好的资源释放方案,推荐在try-catch-finally语句中进行资源的释放
posted @ 2017-02-19 00:02  shugen  阅读(104)  评论(0编辑  收藏  举报