EffectiveJava-7 J避免使用 finalizer方法

来源:互联网 发布:python unicode 编辑:程序博客网 时间:2024/06/05 20:17

避免使用 finalizer 方法


  实际上在实际项目开发中,我基本没有使用到过该方法,原文中介绍了该方法的缺陷,和介绍了显示终结方法的实例,以及 该方法在实际开发中的正确用途,如果真的要使用该方法应该主要的事项

finalizer方法的缺陷

  finalizer 方法通常是不可预的,也是很危险的额,一般情况下是不必要的,Java 语言规范不仅不保证 finalizer
方法会被及时执行,而且根本就不保证它们会被执行,当一个程序终结的时候,某些已经无法访问的对象上的 finalizer() 根本没有被执行,这是完全有可能的额。结论是:不应该依赖 finalizer()方法来更新重要的持久状态。例如,依赖终结方法来释放共享资源(比如上传数据库)
上的永久锁,很容易让整个分布式系统垮掉(没接触过,并不了解)
  不要被System.gcSystem.runFinaliztion 这两个方法所疑惑,它们确实增加了终结方法被执行的机会,但是它们并不保证终结方法一定会被执行。唯一声称保证找终结方法被执行的方法是 System.runFinlizersonExit ,以及它们臭名昭著孪生兄弟Runtime.runFinalizersOnExit, 但是这2个方法都有致命的 缺陷,已经被废弃,不建议使用了。
  未被捕获的异常会使对象处于破坏的状态( a corrupt case),如果另一个线程企图使用这种被破坏的对象,则可能发生任何不确定的行为。正常情况下,未被捕获的异常将会时线程终止,并答应出栈轨迹(Stack Trace),但是,如果异常发生在终结方法总,则不会如此,甚至连警告都不会打出来。
  终结方法还有严重的性能损失。

如何正确终止对象中封装的资源

  显示终止方法的典型例子是 InputStram… 和 java.sql.Connectoin 上的close方法,它执行必要的状态改变,但状态处于非法时,你继续使用将会抛出异常。
  显示的终结方法通常与 try-finally 结构结合起来使用,以确保及时终止。在finally子句内部调用显示的终结方法,可以保证即使在使用对象的时候又异常抛出,该终止方法也会被执行。

    Foo foo = new foo(...);    try{    //做一些会发生异常的事    } finaly{        fpp.terminate();    }

finalizer的合法用途

  第一种用途是,当对象的所有者忘记调用了前面介绍的建议的显示终结方法,finalzier可以充当对象的安全网,虽然,它无法保证终结方法会被及时的调用,但是在客户端无法通过调用显示的终结方法来正常结束的情况下,迟一点释放关键资源总比永远不释放要好。但是如果终结方法的调用时,发现资源确实是还没被释放,你应该用 log 记录起来,因为这意味着你客户端的一个 bug 你应该及时的修复它。
  第二种用途是,与 native method 的使用有关,普通对象通过 native method 委托给一个本地对象,因为native peer 并不是一个普通的方法,所以垃圾回收并不会制动它,当它的Java对象呗回收是,它并不会被会回收。在naatvei peer 并不具备关键的资源的情况下, finalizer 是一个最合适的工具,在native peer拥有必须被及时终止的资源时,那么该类就应该具有一个现实的终止方法。

总结

总之,除非是作为安全网,或者是为了终止非关键的本地资源,否则不建议使用终结方法。如果使用了终结方法,就要记住调用了 super.finalize。

0 0
原创粉丝点击