引言
接上篇文章Object源码分析,我们知道了Java 从 1.0 开始就有了 finalize() 方法,不过这个方法一直被认为是一个糟糕的设计,也是 Java 平台的一个遗留的大“毒瘤”。
垃圾回收器会特别对待覆盖了 finalize() 方法的对象。一般情况下,在垃圾回收期间,一个无法触及的对象会立即被销毁。不过,覆盖了 finalize() 方法的对象会被移动到一个队列里,一个独立的线程遍历这个队列,调用每一个对象的 finalize() 方法。在 finalize() 方法调用结束之后,这些对象才成为真正的垃圾,等待下一轮垃圾回收。
不推荐使用的原因
- finalize()方法不能保证执行。
还有另外一个方法能够回收对象,Runtime.getRuntime().runFinalization(); 但是这只能保证GC做出最大的努力,但是我们也不能finalize方法都能执行。
我们还有一种方式能够保证执行finalize()方法,Runtime.runFinalizersOnExit(true),这个方法已经被JDK弃用,因为这种方法本质上是不安全的,可能导致finalizers方法被活对象调用而其他线程正在并行操作这个对象,从而导致不正确的行为或者死锁。 - finalize()方法不像构造方法在链中工作,意味着像当你调用构造方法的时候,超类中的构造方法也会被隐含的调用,但是在finalize()方法的这种情况中,这种隐含的调用不会发生。超类中的finalize()方法需要显示的调用。
假设,你创建了一个类并且小心翼翼的写了finalize()方法。一些人来extend了你的类,但是在子类中的finalize()块中没有调用super.finalize()方法。然后超类中finalize()方法将永远都不会被调用。 - 任何有finalize()方法抛出的异常都会被GC线程忽略而且不会被进一步传播,事实上也不会在日志文件上记录下来。
正确的姿势
(1)要在finalize()方法中一直调用super.finalize()
(2)考虑到不可预测预测性,不要在时间要求高的应用中使用finalize()
(3)不要使用Runtime.runFinalizersOnExit(true);方法,因为你可能将你的系统置于危险之中
(4)尝试遵循下边的模板使用finalize()方法
@Override
protected void finalize() throws Throwable
{
try{
//release resources here
}catch(Throwable t){
throw t;
}finally{
super.finalize();
}
}
作者:select you from me
链接:https://mp.csdn.net/mdeditor/97019467
来源:CSDN
转载请联系作者获得授权并注明出处。