如果我关闭基础流,是否真的存在资源泄漏



我在我们的一个程序上运行了一个动态代码分析工具,这种模式被识别为资源泄漏:

...
FileInputStream fileInputStream = new FileInputStream(file);
try {
    data = someMethod(new BufferedInputStream(fileInputStream));
    // Assume that someMethod(InputStream) internally reads the stream
    // until BufferedInputStream.read() returns -1.
    ...
}
finally {
    ...
    try {
        fileInputStream.close();
    } catch (IOException e) {
        ...
    }
}

具体而言,分析工具将new BufferedInputStream(...)调用标记为资源泄漏,因为它永远不会关闭。 但是,在此模式中,基础流fileInputStream已关闭,BufferedInputStream超出范围。

注意:当我最初发布问题时,我忽略了明确说明,但我意识到这不是"最佳"实现。但是,如果这里没有事实上的资源泄漏,那么我们不太可能在我们的旧代码库中搜索此模式的所有实例并关闭外部流或用较新的结构(例如 try-with-resources)替换它们 - 即"如果它没有损坏,就不要修复它。

在这种情况下,这实际上是资源泄漏吗?

这不太可能是实际的资源泄漏,但编写这样的代码绝对不是最佳实践。

通常,您应该始终在最外层的流上调用close,这将波及到内部流。

如果您使用的是 Java 7,则可以使用新的 try-with-resources 语法,并完全避免使用 finally 块。

相关:尝试资源声明

在这种情况下没有资源泄漏。 但是,关闭BufferedInputStream的成本是最小的(或关闭的),因此最简单的方法是添加(严格)不必要的关闭以使分析工具满意。

典型的静态分析工具是在代码中寻找指示错误的结构模式。 在这种情况下,模式匹配方法会给出资源泄漏的误报。

因为 Java 没有解构函数,所以超出范围的对象不一定会关闭流。Java确实有终结器,但不能保证它们会被调用。BufferedInputStream 不一定会关闭。但是,由于底层流是关闭的,我认为这并不重要。

更好的做法是确保流已关闭,但这可能无关紧要。

最新更新