博客搬家自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"); } }}第一次对该对象清理会调用它的finalize函数,虽然系统中的引用已经被清除,但是作为实例方法finalize,对象的this引用依然会被传入方法内部,如果引用外泄,对象就会复活。而finalize函数只会调用一侧,所以,第二次清楚对象的时候,对象就没有机会再复活。
finalize函数是一个非常糟糕的模式,不推荐大家使用finalize函数来释放资源。
因为: >
finalize函数有可能发生引用外泄,在无意中复活对象. 由于finalize是被系统调用的,调用的时间不明确,因此不是一个很好的资源释放方案,推荐在try-catch-finally语句中进行资源的释放新闻热点
疑难解答