《Effective Java 中文版 第2版》学习笔记 第7条:避免使用终结方法
Posted 王景迁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Effective Java 中文版 第2版》学习笔记 第7条:避免使用终结方法相关的知识,希望对你有一定的参考价值。
在Java中,当一个对象变得不可到达时,垃圾回收器会回收与该对象相关联的存储空间。用try-finally块来回收其他的非内存资源。
终结方法的缺点在于不能保证会被及时地执行。从一个对象变得不可到达开始,到它的终结方法被执行,所花费的这段时间是任意长的。这意味着注重时间的任务不应该由终结方法来完成。例如,用终结方法来关闭已经打开的文件是错误的,因为打开文件的描述符是一种很有限的资源。由于JVM会延迟执行终结方法,所以大量的文件会保留在打开状态,当一个程序再不能打开文件的时候,它可能会运行失败。
及时地执行终结方法是垃圾回收算法的一个主要功能,这种算法在不同的JVM实现中会大相径庭。如果程序依赖于终结方法被执行的时间点,这个程序的行为在不同的JVM中运行的表现可能会截然不同。一个程序在自己测试用的JVM平台上运行得非常好,而在客户的JVM平台上可能根本无法运行。
Java语言规范不仅不保证终结方法会被及时地执行,而且根本就不保证它们会被执行。当一个程序终止时,某些已经无法访问的对象上的终结方法可能根本没有被执行。所以,不应该依赖终结方法来更新重要的持久状态。例如,依赖终结方法来释放共享资源(比如数据库)上的永久锁,很容易让整个分布式系统垮掉。
System.gc和System.runFinalization这两个方法虽然增加了终结方法被执行的机会,但是不保证一定会执行终结方法。System.runFinalizersOnExit以及其孪生兄弟Runtime.runFinalizersOnExit这两个方法虽然声称保证终结方法被执行,但是都有致命的缺陷,已经被废弃了。
如果未被捕获的异常在终结过程中被抛出来,这种异常会被忽略,并且该对象的终结过程也会终止。换言之,如果异常发生在终结方法之中,它不会使线程终止,也不会打印出栈轨迹(Stack Trace),甚至不会打印警告。
使用终结方法会有严重的(Severe)性能损失。也就是说,增加终结方法会使处理速度变慢。
如果类的对象中封装的资源(例如文件或者线程)需要终止,只需提供一个显式的终止方法,并要求该类的客户端在每个实例不再有用时调用这个方法。其中,显式的终止方法必须在一个私有域中记录下“该对象已经不再有效”。如果终止方法是在对象已经终止之后被调用,其他的方法必须检查这个域,并抛出IllegalStateException异常。显式的终结方法通常与try-finally结构结合起来使用,确保及时终止。在finally子句内部调用显式的终止方法,保证即使在使用对象时抛出异常,该终止方法也会执行。
终结方法有两种合法用途。
第一种用途:当对象的所有者忘记调用显式终止方法时,终结方法可以充当“安全网(safety net)”,迟一点释放关键资源总比永远不释放要好。
第二种用途:本地对等体(native peer)是一个本地对象(native object),普通对象通过本地方法(native method)委托给一个本地对象。因为本地对等体不是一个普通对象,所以垃圾回收器不会知道它,当它的Java对等体被回收时,它不会被回收。在本地对等体不拥有关键资源的前提下,终结方法会回收它。如果本地对等体拥有必须被及时终止的资源,该类就应该具有一个显式的终止方法。终止方法可以是本地方法,也可以调用本地方法。
“终结方法链(finalizer chaining)”不会被自动执行。如果类(不是Object)有终结方法,并且子类覆盖了终结方法,子类的终结方法就必须手工调用超类的终结方法。在一个try块中终结子类,并在相应的finally块中调用超类的终结方法。保证即使子类的终结过程抛出异常,超类的终结方法也会得到执行。
1 @Override 2 protected void finalize() throws Throwable { 3 try { 4 ... // 终结子类状态 5 } finally { 6 super.finalize(); // 终结父类状态 7 } 8 }
总之,除非是作为安全网,或者是为了终止非关键的本地资源,否则请不要使用终结方法。
参考资料
《Effective Java 中文版 第2版》 P24-27
以上是关于《Effective Java 中文版 第2版》学习笔记 第7条:避免使用终结方法的主要内容,如果未能解决你的问题,请参考以下文章
《Effective Java 中文版 第2版》学习笔记 第6条:消除过期的对象引用
Effective Java中文版(第2版) PDF分享下载