在我直接与他们合作或花时间了解他们之后,我经常发现自己会更多地关注在线话题。最近 Stephen Connolly (CloudBees) 的帖子 FileInputStream / FileOutputStream Considered Harmful 引起了我的注意,因为 我最近的问题 Java 的终结器。在 那篇文章 中,作者谈到了 java.io.FileInputStream 和 java.io.FileOutputStream 实现重写的 finalize( ) 方法 FileInputStream.finalize() 和 FileOutputStream.finalize()。关于在 JDK 9 中弃用终结器,我的观点是,一个我多年未曾想过的话题突然出现在我身边。
Connolly 的帖子引用了 Hadoop JIRA HDFS-8562(“HDFS Performance is impacted by FileInputStream Finalizer”)。该 JIRA 于 2015 年 6 月开放,其描述包括有趣的背景,说明为什么 FileInputStream
的终结器会导致使用 HDFS 的人出现问题。这个 JIRA 也很有趣,因为它研究了为什么将 FileInputStream
和 FileOutputStream
更改为不使用 protected
finalize()
方法。
JDK-8080225(“FileInputStream cleanup should be improved.”)在 HDFS-8562 中引用并于 2015 年 5 月编写。它指出,“FileInputStream 依赖于完成执行如果 FIS 尚未关闭,final 将关闭。这会导致突发性 GC 的额外工作。 FileInputStreams 的清理应该尽快进行,并且不会增加 GC 的开销。”艾伦·贝特曼 (Alan Bateman) 对此发表了评论,称“可以通过使用 Files.newInputStream 轻松解决此问题。” Roger Riggs 写到充分解决这个问题的困难,“由于未知/不可知有多少 FIS/FOS 子类可能依赖于重写关闭或最终确定兼容性问题是严重的。只有长期(多次发布)限制弃用或使覆盖无效才有可能最终消除兼容性问题。”
Connolly 在文章结尾提到 Jenkins 通过 JENKINS-42934(“避免使用新的 FileInputStream / new FileOutputStream”)改变了这一点。将 new FileInputStream
更改为 Files.newInputStream
的示例可从那里获得。
事实上,我已经能够使用 Java 这么多年而不用担心终结器,即使我使用了诸如 FileInputStream
之类的类,这一事实本身也证明了这些类与 finalize()
的使用是有限的> 实现不一定会导致垃圾收集或其他问题。我喜欢 Colin P. McCabe 在 HDFS JIRA 中对此问题的阐述:非常少量的对象。就像我之前提到的,我们遇到的终结器的大问题是短路读取流缓存。如果我们能解决这个问题,就像这个补丁试图做的那样,我们将消除大部分问题。”换句话说,并非所有 FileInputStream
和 FileOutputStream
的使用都值得关注。使用工具来识别与终结器相关的异常高的垃圾收集是识别那些需要解决的问题的最佳方法。
在多年的 Java 开发中,我没有使用过或案例过 Java 终结器。最近几个月,我看到越来越多的人在处理这个问题。 弃用 Java 终结器 是将其从核心 API 中移除的良好开端。
标签2: Java教程地址:https://www.cundage.com/article/jcg-java-finalizer-java-file-inputoutput-streams.html