Java 资源管理:了解 Findbugs 结果
Posted
技术标签:
【中文标题】Java 资源管理:了解 Findbugs 结果【英文标题】:Java resource management: understanding Findbugs results 【发布时间】:2011-01-27 08:44:18 【问题描述】:Findbugs 让我对打开两个 Closeable
实例的方法感到不满,但我不明白为什么。
来源
public static void sourceXmlToBeautifiedXml(File input, File output)
throws TransformerException, IOException, JAXBException
FileReader fileReader = new FileReader(input);
FileWriter fileWriter = new FileWriter(output);
try
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
finally
try
fileReader.close();
finally
fileWriter.close();
查找错误分析
Findbugs 告诉我
Method [...] may fail to clean up java.io.Reader [...]
并指向带有FileReader fileReader = ...
的行
问题
谁错了:我还是 Findbugs?
【问题讨论】:
【参考方案1】:FindBugs 正确:如果 FileWriter 的构造函数抛出异常,文件阅读器不会被关闭。要验证这一点,请尝试为 output
传递一个无效的文件名。
我会这样做:
FileReader fileReader = new FileReader(input);
try
FileWriter fileWriter = new FileWriter(output);
try
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
finally
fileWriter.close();
finally
fileReader.close();
请注意,可以改进对关闭时抛出的异常的处理,因为通过抛出异常离开 finally 块将导致 try 语句通过抛出该异常而终止,吞下 try 块中抛出的任何异常,这通常对调试更有用。有关如何避免这种情况的简单方法,请参阅 duffymo 的回答。
编辑:从 Java 7 开始,我们可以使用 try-with-resources 语句,它允许正确和简洁地处理这些极端情况:
try (
FileReader fileReader = new FileReader(input);
FileWriter fileWriter = new FileWriter(output)
)
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
【讨论】:
+1 是唯一一个注意到 constructor 可以抛出的人。就个人而言,我会在try
内调用 ctors(将变量显式初始化为 null
外),然后在 finally 内使用 Jakarta IOUtils.closeQuietly()
。
FileReader
和 FileWriter
的实际实现非常糟糕,以至于在打开文件后它们可能会抛出异常(并且由于它来自构造函数,因此您没有关闭的引用自己做)。另请注意,您正在隐式使用当时恰好配置为默认值的任何字符集编码,这绝不是一个好主意。
很好 - 我要 +1 不是因为可以改进异常处理,这不仅会导致从 finally 抛出会吞下潜在的 try 异常,而且很可能会导致 close() 异常意义重大。
我在哪里说过它们不重要?我的代码不会抑制它们,是吗?【参考方案2】:
即使对于 findbugs,这也可能很复杂。
try
fileReader.close();
finally
fileWriter.close();
在我看来你是对的。
编辑:哇,我以为我会因为说 findbugs 可能出错而被否决!
EDIT:看起来 FindBugs 是对的。不错的收获。
【讨论】:
好吧,如果你说 findbugs 是错了,我可能会投反对票,但你说它可以肯定是正确的.【参考方案3】:我会说是你。
我会在单独的 try/catch 块中关闭这两个资源。我会创建静态方法来帮助我:
public static void sourceXmlToBeautifiedXml(File input, File output)
throws TransformerException, IOException, JAXBException
FileReader fileReader = new FileReader(input);
FileWriter fileWriter = new FileWriter(output);
try
// may throw something
sourceXmlToBeautifiedXml(fileReader, fileWriter);
finally
close(fileReader);
close(fileWriter);
// same for reader & writer
public static void close(InputStream s)
try
if (s != null)
s.close();
catch (IOException e)
e.printStackTrace();
【讨论】:
嗯,我不敢相信这是关闭多个资源时的常见模式。这有什么模式吗? 肯定有 JDBC。 ResultSet、Statement 和 Connection 很常见。 我不知道是不是“模式”,但是我写的就是那个静态方法。 这个答案只是令人困惑 - 没有解决已接受的答案中解决的真正问题。请考虑编辑它-1【参考方案4】:我认为 findbugs 是对的。
finally
try
fileReader.close();
finally
fileWriter.close();
在此块中,您尝试关闭 FileReader。然而,这可能会引发异常,并在嵌套的最后关闭 fileWriter。您是否尝试在同一个 finally 块中关闭两个阅读器?那么 findbugs 怎么说呢?
finally
try
fileReader.close();
fileWriter.close();
finally
//dunno maybe log that something went wrong.
【讨论】:
如果 fileReader.close() 抛出 IOException,fileWriter 将永远不会被关闭。 您的批评者适用于您的第二个代码示例。 -- 是的fileReader.close()
可能会抛出IOExceptioon
,这就是为什么在我的示例中fileWriter.close
位于finally 块中:如果关闭fileReader 失败,则无论如何都会关闭fileWriter。
该死。得到我。经验法则:在你喝第一杯咖啡之前不要去 *** ;-)
请删除这个 - 不添加任何值 -1以上是关于Java 资源管理:了解 Findbugs 结果的主要内容,如果未能解决你的问题,请参考以下文章
idea 安装findBugs 可以做代码扫描,也可以导出扫描结果生成扫描报告