我有一个try-with-resources块,它启动了一些可自动关闭的对象
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("some-file), "UTF-8"))) {
......
} catch (IOException e) {
.....
}
强化扫描报告了此问题
...有时...中的功能 无法释放由FileInputStream()分配的系统资源 行....
我想知道上面的代码有什么问题。我认为try-with-resources可以处理多个自动关闭的对象。任何想法是什么问题?谢谢。
答案 0 :(得分:0)
当然Fortify抱怨它不应该做的事情(误报),但是上面的代码实际上可能泄漏FileInputStream对象。考虑一下InputStreamReader构造函数引发异常时会发生什么。在这种情况下,我们当然已经创建了FileInputStream,但是不会清除它。
您似乎给人的印象是,实现AutoCloseable的表达式中遇到的每个对象都将由try-with-resources语句进行管理。但是,如果您查看语言规范:https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
try ({VariableModifier} R Identifier = Expression ...)
Block
被翻译成:
{
final {VariableModifierNoFinal} R Identifier = Expression;
Throwable #primaryExc = null;
...
因此,只有表达式(在您的情况下为BufferedReader)的“最终结果”会自动关闭。 (通常,组成的流/阅读器/编写器会在链中推动关闭操作,但请记住,我们的前提是其中一个构造函数因异常而失败。)
您可以通过为链中的每个元素声明单独的变量来解决编码问题:
try (FileInputStream fis = new FileInputStream("some-file");
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(isr)) {
//...
}
这个例子或多或少在Fortify security issue "Unreleased resource stream" for try-with-resource。