为什么我用包装编写器对象得到“潜在的资源泄漏”警告?

时间:2013-04-10 11:30:39

标签: java eclipse resources warnings

下面是一个简化的示例,它将导致Eclipses Java系统为表达式Potential resource leak: '<unassigned Closeable value>' may not be closed发出警告new BufferedWriter(...)

    boolean useStdout = askUserWhetherToUseStdout();
    Writer writer = useStdout ? new OutputStreamWriter(System.out) : new BufferedWriter(new FileWriter(new File(askUserForFilename())));
    try
    {
        writer.write("Hello World!");
    }
    finally
    {
        writer.close();
    }

这是假阳性吗?我理解整个作家的方式是,任何作家都会关闭其底层作家。在我的例子中,writer将封装新的缓冲编写器(后者又封装文件编写器),因此关闭writer不应泄漏与缓冲编写器相关的任何资源,或者反过来,它的底层编写器?

我在这里缺少什么?

3 个答案:

答案 0 :(得分:2)

根据更新后的问题编辑回答:

这是一个虚假的警告 - 基于使用三元运算符。如果操作的右侧没有触发,那么将不会创建BufferedWriter,并且没有资源泄漏。所以警告描述的内容实际上是不可能的。但是,如果你想“处理”它,只需在try块中移动编写器的创建。

boolean useStdout = askUserWhetherToUseStdout();
Writer writer = null;
try {
    writer = useStdout ? new OutputStreamWriter(System.out)
            : new BufferedWriter(new FileWriter(new File(
                    askUserForFilename())));
    writer.write("Hello World!");
} finally {
    if (writer != null)
        writer.close();
}

答案 1 :(得分:1)

如果writer.write("Hello World!");抛出异常,则永远不会调用writer.close()

尝试将其包装到try-catch块中(可能使用自动关闭功能,请参阅http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html)。

答案 2 :(得分:1)

你能检查一下这段代码是否会给你警告吗?如果没有那么你可能在创建编写器时没有处理IOException,这也应该在try块中完成。

boolean useStdout = askUserWhetherToUseStdout();
Writer writer = null;
try {
    writer = useStdout ? new OutputStreamWriter(System.out)
            : new BufferedWriter(new FileWriter(new File(
                    askUserForFilename())));
    writer.write("Hello World!");
} catch (IOException e) {
    e.printStackTrace();
} finally {
    try {
        if (writer != null)
            writer.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

您还可以使用try-with-resources,它会在try块后自动关闭资源流。

boolean useStdout = askUserWhetherToUseStdout();
try (Writer writer = useStdout ? new OutputStreamWriter(System.out)
        : new BufferedWriter(new FileWriter(new File(
                askUserForFilename())))) {
    writer.write("Hello World!");
} catch (IOException e) {
    e.printStackTrace();
}