我有一个try-with-resources块,可以启动一些自动关闭的对象。
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("some-file), "UTF-8"))) {
......
} catch (IOException e) {
.....
}
加强扫描报告这个问题
在......中的函数......有时无法释放FileInputStream()在......行分配的系统资源。
我想知道上面的代码有什么问题。我以为try-with-resources可以处理多个自动关闭的对象。有什么想法,问题出在哪里?谢谢你。
当然,Fortify会抱怨一些不该抱怨的事情(误报),但上面的代码实际上会泄露FileInputStream对象。 考虑一下如果InputStreamReader构造函数抛出异常会发生什么。在这种情况下,我们当然已经创建了FileInputStream,但它不会被清理掉。
你似乎认为,实现AutoCloseable的表达式中遇到的每个对象都会被try-with-resources语句管理。然而,如果你看一下语言规范。https:/docs.oracle.comjavasetutorialessentialexceptionstryResourceClose.html。
try ({VariableModifier} R Identifier = Expression ...)
Block
被翻译成。
{
final {VariableModifierNoFinal} R Identifier = Expression;
Throwable #primaryExc = null;
...
所以,只有表达式的 "最终结果"(在你的例子中是BufferedReader)被自动关闭。通常情况下,组成的streamsreaderswriters会将关闭操作向下传播,但请记住,我们这里的前提是其中一个构造函数出现异常而失败)。
你可以通过为链中的每个元素单独声明变量来解决编码问题。
try (FileInputStream fis = new FileInputStream("some-file");
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
BufferedReader bufferedReader = new BufferedReader(isr)) {
//...
}
同样的例子可以在 强化try-with-resource的安全问题 "未释放的资源流"。.