在try-with-resources块中加强对资源的抱怨

时间:2018-06-27 21:17:40

标签: fortify try-with-resources

我有一个try-with-resources块,它启动了一些可自动关闭的对象

    try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("some-file), "UTF-8"))) {
         ......
    } catch (IOException e) {
        .....
    }

强化扫描报告了此问题

  

...有时...中的功能   无法释放由FileInputStream()分配的系统资源   行....

我想知道上面的代码有什么问题。我认为try-with-resources可以处理多个自动关闭的对象。任何想法是什么问题?谢谢。

1 个答案:

答案 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