我们都知道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. 虚拟机下安装centos7方法,修改系统语言为简体中文的方法

    说明 自己装系统时一般都可以自定义选择系统语言.可是云端服务器一般都是安装好的镜像,默认系统语言为英文,对于初学者可能还会有搞不懂的计算机词汇.这里简单说一下centos7怎么修改系统语言为中文. 虚 ...

  2. 设置Mybatis打印调试sql的两种方式

    http://blog.csdn.net/gao36951/article/details/53641432 ********************************************* ...

  3. Bootstrap学习笔记(3)--菜鸟网CDN

    Bootstrap CDN 推荐 本站实例采用的是自建的静态资源库上的Bootstrap资源. <!-- 新 Bootstrap 核心 CSS 文件 --> <link href=& ...

  4. OpenERP 7 picking order 继承需要注意的地方

    stock.picking.out  和 stock.picking.in 都是继承自stock.picking 新添加columns时需要注意,在stock.picking.out和stock.pi ...

  5. HTML5 + AJAX ( jQuery版本 ) 文件上传带进度条

    页面技术:HTML5 + AJAX ( jQuery) 后台技术:Servlet 3.0 服务器:Tomcat 7.0 jQuery版本:1.9.1 Servlet 3.0 代码 package or ...

  6. 搭建自己的GitHub Pages

    本文记录博主使用Win 10操作系统和Jekyll 3.1.2搭建GitHub Pages的过程.希望能帮助到相同有需要的朋友. 基本需求 GitHub账号及一个命名为{GitHub昵称}.githu ...

  7. gt811 driver

    #include <linux/module.h> #include <linux/i2c.h> #include <linux/platform_device.h> ...

  8. PLSQL 连接不上64位ORACLE数据库解决办法

    http://it.oyksoft.com/post/6003/ huan jing bian liang TNS_ADMIN  D:\OracleClient D:\OracleClient\TNS ...

  9. jvm 调整tomcat的堆内存和常驻内存catalina.sh

    4.2 性能优化 tomcat性能取决于你的内存大小 上策:优化代码 中策:jvm优化机制  垃圾回收机制 把不需要的内存回收   优化jvm--优化垃圾回收策略 优化catalina.sh配置文件. ...

  10. 数学 + 带权中位数 - SGU 114 Telecasting station

    Telecasting station Problem's Link Mean: 百慕大的每一座城市都坐落在一维直线上,这个国家的政府决定建造一个新的广播电视台. 经过了许多次试验后,百慕大的科学家们 ...