我们都知道finalize()方法是回收分配给对象的内存之前调用垃圾收集器线程的基本语句。在这篇文章中,我们将会深入这个方法。

这篇文章中的章节:

1、finalize()方法不能保证执行(这个将要用例子来说明)

2、其他不使用它的原因

3、finalize()方法在性能上增加负担

4、正确使用的指导

finalize()方法不能保证执行(这个将要用例子来说明)

让我们使用一个程序证明它,我已经写了一个简单的Java runnable例子,在try-catch-finally-finalize块中每个里边都有输出语句。我已经创建了另一个类,并创建runnable的三个实例,然后我们看一下执行的过程。
  1. public class TryCatchFinallyTest implements Runnable {
  2. private void testMethod() throws InterruptedException
  3. {
  4. try
  5. {
  6. System.out.println("In try block");
  7. throw new NullPointerException();
  8. }
  9. catch(NullPointerException npe)
  10. {
  11. System.out.println("In catch block");
  12. }
  13. finally
  14. {
  15. System.out.println("In finally block");
  16. }
  17. }
  18. @Override
  19. protected void finalize() throws Throwable {
  20. System.out.println("In finalize block");
  21. super.finalize();
  22. }
  23. @Override
  24. public void run() {
  25. try {
  26. testMethod();
  27. } catch (InterruptedException e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. }
 
  1. public class TestMain
  2. {
  3. @SuppressWarnings("deprecation")
  4. public static void main(String[] args) {
  5. for(int i=1;i<=3;i++)
  6. {
  7. new Thread(new TryCatchFinallyTest()).start();
  8. }
  9. }
  10. }
  11. Output:
  12. In try block
  13. In catch block
  14. In finally block
  15. In try block
  16. In catch block
  17. In finally block
  18. In try block
  19. In catch block
  20. In finally block

很神奇,线程中的finalize方法一点也没有执行,这已经证明了我刚刚说明的事情。我想发生这件事的原因是:finalizer是由垃圾收集器中的独立线程控制执行的,如果Java虚拟机存在太久,垃圾回收器没有时间创建和执行finalizers,如果错了,请说明。

下一个问题是,我们能够强制它执行吗
答案是:是的,可以,使用Runtime.runFinalizersOnExit(true);方法
  1. public class TestMain
  2. {
  3. @SuppressWarnings("deprecation")
  4. public static void main(String[] args) {
  5. for(int i=1;i<=3;i++)
  6. {
  7. new Thread(new TryCatchFinallyTest()).start();
  8. Runtime.runFinalizersOnExit(true);
  9. }
  10. }
  11. }
  12. Output:
  13. In try block
  14. In catch block
  15. In finally block
  16. In try block
  17. In try block
  18. In catch block
  19. In finally block
  20. In catch block
  21. In finally block
  22. In finalize block
  23. In finalize block
  24. In 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()方法
  1. @Override
  2. protected void finalize() throws Throwable
  3. {
  4. try{
  5. //release resources here
  6. }catch(Throwable t){
  7. throw t;
  8. }finally{
  9. super.finalize();
  10. }
  11. }
原文链接:http://howtodoinjava.com/2012/10/31/why-not-to-use-finalize-method-in-java/

为什么在Java中不使用finalize()方法的更多相关文章

  1. JAVA中GC时finalize()方法是不是一定会被执行?

    在回答上面问题之前,我们一定要了解JVM在进行垃圾回收时的机制,首先: 一.可达性算法  要知道对象什么时候死亡,我们需要先知道JVM的GC是如何判断对象是可以回收的.JAVA是通过可达性算法来来判断 ...

  2. finalize() 方法——Java中垃圾回收提醒方法

    finalize() Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize( ),它用来清除回收对象. 例如,你可以使用 finalize() 来确保 ...

  3. 【Java面试题系列】:Java中final finally finalize的区别

    本篇为[Java面试题系列]第三篇,文中如有错误,欢迎指正. 第一篇链接:[Java面试题系列]:Java基础知识常见面试题汇总 第一篇 第二篇链接:[Java面试题系列]:Java基础知识常见面试题 ...

  4. java中substring的使用方法

    java中substring的使用方法 str=str.substring(int beginIndex);截取掉str从首字母起长度为beginIndex的字符串,将剩余字符串赋值给str: str ...

  5. Java中Set的contains()方法

    Java中Set的contains()方法 -- hashCode与equals方法的约定及重写原则 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashCode() a ...

  6. [java,2017-05-16] java中清空StringBuffer的方法以及耗费时间比较

    java中清空StringBuffer的方法,我能想到的有4种: 1. buffer.setLength(0);  设置长度为0 2. buffer.delete(0, buffer.length() ...

  7. java中BorderLayout的使用方法

    相关设置: 使用BorderLayout布局上下左右中布局5个按键,单击中间的那个按键时就关闭窗口 代码: /**** *java中BorderLayout的使用方法 * 使用BorderLayout ...

  8. 【Java】Java中常用的String方法

    本文转载于:java中常用的String方法 1 length()字符串的长度 String a = "Hello Word!"; System.out.println(a.len ...

  9. Java中Set的contains()方法——hashCode与equals方法的约定及重写原则

    转自:http://blog.csdn.net/renfufei/article/details/14163329 翻译人员: 铁锚 翻译时间: 2013年11月5日 原文链接: Java hashC ...

随机推荐

  1. Java GC 日志解析

    JVM 在Java应用程序优化中是不可缺少的一大重项,如何合理配置Java参数,如果验证配置参数的有效性,从GC日志中可以获得很重要的提示,以下是笔者对GC垃圾收集器默认开启的组合日志的部分的解析,希 ...

  2. javac使用笔记

    一般写java都用的IDE,今天临时要测试一下JDK安装好没,就用了一下javac,结果各种不会用 目录 javac -help查到了有javac -sourcepath,他喵的我还以为这是查找sou ...

  3. Psql 安装问题

    在openerp安装过程中报错: psql: could not connect to server: No such file or directory Is the server running ...

  4. at91 uart driver for vxworks

    /* at91UART.c - AT91RM9200 serial driver */ /* Copyright 2003-2004 Coordinate Co., Ltd. */ /* Copyri ...

  5. 重启oracle方法一二三

    startup nomount alter database mount alter database open Linux:方法1 用root以ssh登录到linux,打开终端输入以下命令: cd ...

  6. python ascii codec can't decode

    提示错误: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 240: ordinal not in range ...

  7. 2015 Multi-University Training Contest 3 1006 Beautiful Set

    Beautiful Set Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5321 Mean: 给出一个集合,有两种计算集合的值的 ...

  8. [android] AndroidManifest.xml【 manifest -> uses-permission】

    在  API Level 1 时被引入 简介: 在某些情况下,你为app设置的权限将会影响到google应用商店会用何种规则来过滤你的APP. 如果你需要一个硬件相关的权限——CAMERA,googl ...

  9. 【BZOJ】1492: [NOI2007]货币兑换Cash(cdq分治)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1492 蒟蒻来学学cdq神算法啊.. 详见论文 陈丹琦<从<Cash>谈一类分治算法 ...

  10. 【BZOJ】1684: [Usaco2005 Oct]Close Encounter(暴力+c++)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1684 这货完全在考精度啊.. 比如奇葩 (llf)a/b*i (llf)(a/b*i)和(llf)( ...