为什么在Java中不使用finalize()方法
来源:互联网 发布:长歌门捏脸数据 编辑:程序博客网 时间:2024/04/30 20:49
我们都知道finalize()方法是回收分配给对象的内存之前调用垃圾收集器线程的基本语句。在这篇文章中,我们将会深入这个方法。
这篇文章中的章节:
1、finalize()方法不能保证执行(这个将要用例子来说明)
2、其他不使用它的原因
3、finalize()方法在性能上增加负担
4、正确使用的指导
finalize()方法不能保证执行(这个将要用例子来说明)
让我们使用一个程序证明它,我已经写了一个简单的Java runnable例子,在try-catch-finally-finalize块中每个里边都有输出语句。我已经创建了另一个类,并创建runnable的三个实例,然后我们看一下执行的过程。
public class TryCatchFinallyTest implements Runnable { private void testMethod() throws InterruptedException { try { System.out.println("In try block"); throw new NullPointerException(); } catch(NullPointerException npe) { System.out.println("In catch block"); } finally { System.out.println("In finally block"); } } @Override protected void finalize() throws Throwable { System.out.println("In finalize block"); super.finalize(); } @Override public void run() { try { testMethod(); } catch (InterruptedException e) { e.printStackTrace(); } }}
public class TestMain{ @SuppressWarnings("deprecation") public static void main(String[] args) { for(int i=1;i<=3;i++) { new Thread(new TryCatchFinallyTest()).start(); } }} Output: In try blockIn catch blockIn finally blockIn try blockIn catch blockIn finally blockIn try blockIn catch blockIn finally block
很神奇,线程中的finalize方法一点也没有执行,这已经证明了我刚刚说明的事情。我想发生这件事的原因是:finalizer是由垃圾收集器中的独立线程控制执行的,如果Java虚拟机存在太久,垃圾回收器没有时间创建和执行finalizers,如果错了,请说明。
下一个问题是,我们能够强制它执行吗
答案是:是的,可以,使用Runtime.runFinalizersOnExit(true);方法
public class TestMain{ @SuppressWarnings("deprecation") public static void main(String[] args) { for(int i=1;i<=3;i++) { new Thread(new TryCatchFinallyTest()).start(); Runtime.runFinalizersOnExit(true); } }} Output: In try blockIn catch blockIn finally blockIn try blockIn try blockIn catch blockIn finally blockIn catch blockIn finally blockIn finalize blockIn finalize blockIn finalize block
还有另一个方法,Runtime.getRuntime().runFinalization(); 但是这只能保证GC做出最大的努力,即使在我们的程序中,我们也不能保证3个线程中的finalize方法都能执行。
前一步,我们使用Runtime.runFinalizersOnExit(true); 方法,这是另一个遗憾,这个方法已经被JDK弃用,原因是:这种方法本质上是不安全的,可能导致finalizers方法被活对象调用而其他线程正在并行操作这个对象,从而导致不正确的行为或者死锁。所以,我们不能以一种方式执行它而以另一种方式置系统于危险中,最好我们不使用它。
其他不使用它的原因
(1)finalize()方法不像构造方法在链中工作,意味着像当你调用构造方法的时候,超类中的构造方法也会被隐含的调用,但是在finalize()方法的这种情况中,这种隐含的调用不会发生。超类中的finalize()方法需要显示的调用。
假设,你创建了一个类并且小心翼翼的写了finalize()方法。一些人来extend了你的类,但是在子类中的finalize()块中没有调用super.finalize()方法。然后超类中finalize()方法将永远都不会被调用。
(2)任何有finalize()方法抛出的异常都会被GC线程忽略而且不会被进一步传播,事实上也不会在日志文件上记录下来。
finalize()方法在性能上增加负担
在第二版的effective Java中,作者说:“这有另外一件事,使用finalize()方法还有另外的严重的性能问题,在我的机器上,创建和销毁一个简单的对象的时间大概是5.6ns,增加finalize()方法这个时间增加到2400ns,换句话说,使用finalize()方法创建和销毁对象比不使用慢了430倍”。我也在我的系统上分析上述问题,但是没有这么大的差别,但是也是有一些差别的。但是在时间要求高的系统内,这也是一个很大的区别。
正确使用的指导
经过上边的讨论之路,如果你依旧发现在一些场景下使用finalize()方法是别要的,那么请检查下边的观点
(1)要在finalize()方法中一直调用super.finalize()
(2)考虑到不可预测预测性,不要在时间要求高的应用中使用finalize()
(3)不要使用Runtime.runFinalizersOnExit(true);方法,因为你可能将你的系统置于危险之中
(4)尝试遵循下边的模板使用finalize()方法
@Overrideprotected void finalize() throws Throwable{ try{ //release resources here }catch(Throwable t){ throw t; }finally{ super.finalize(); }}
原文链接:http://howtodoinjava.com/2012/10/31/why-not-to-use-finalize-method-in-java/
0 0
- 为什么在Java中不使用finalize()方法
- Java 中finalize()方法使用
- 在finalize方法中复活java对象
- java中什么时候使用finalize()方法
- java中finalize()方法
- java中finalize()方法
- Java中finalize方法
- Java finalize方法使用
- Java finalize方法使用
- Java finalize方法使用
- Java finalize方法使用
- Java finalize方法使用
- Java finalize方法使用
- Java finalize方法使用
- Java finalize方法使用
- Java finalize方法使用
- Java finalize方法使用
- Java finalize方法使用
- 《STL源码剖析》深入分析序列式容器——vector
- 《剑指offer》——跳台阶
- Huatuo's Medicine 【水题】
- 集合运算时使用更优雅的方式
- 浅谈Java中的System.out.println()
- 为什么在Java中不使用finalize()方法
- 在EA中将代码导入模型的时候,查看源码出现中文乱码的解决方案
- 《剑指offer》——变态跳台阶
- shell join命令详解(转)
- c++ primer第五版(中文)习题答案 第二章第四节-const限定符
- ajax实现简单的多人聊天
- Mangos源码分析(14):Mangos预编译头文件及模块划分随想
- lua语言中与时间相关的函数总结
- 黑马程序员——C语言指针