Java 如果关闭底层流,是否真的存在资源泄漏?

Java 如果关闭底层流,是否真的存在资源泄漏?,java,bufferedinputstream,resource-leak,Java,Bufferedinputstream,Resource Leak,我在我们的一个程序上运行了动态代码分析工具,该模式被确定为资源泄漏: ... FileInputStream fileInputStream = new FileInputStream(file); try { data = someMethod(new BufferedInputStream(fileInputStream)); // Assume that someMethod(InputStream) internally reads the stream // u

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

...
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) {
        ...
    }
}
具体来说,分析工具将
新BufferedInputStream(…)
调用标记为资源泄漏,因为它从未关闭过。但是,在此模式中,基础流
fileInputStream
关闭,而
BufferedInputStream
超出范围

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


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

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


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

这不太可能是实际的资源泄漏,但编写这样的代码肯定不是最佳做法

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

如果您使用的是Java7,那么就可以使用新的try with resources语法,并完全避免使用finally块


相关:

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


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

谢谢;对于一般情况,建议使用资源进行尝试。然而,在我的特殊情况下,我们不太可能预算时间在现有代码库中查找和更新此模式的所有实例,除非存在重大的、事实上的资源泄漏。我的第二个目标可能与大多数人无关,但是我还试图确定分析工具是否发现了真正的bug,或者它的启发式算法是否将误报标记为bug。@rob我认为问题在于,如果不查看某个方法的实现,您就无法确定是否发生了资源泄漏。我同意Stephen的观点,对于大多数合理的实现来说,这不会是一个问题。@rob我对这种风格变化的一般规则是,当你遇到它们时,一次清理一点。我同意你的观点,在公司范围内宣布一夜之间改变这种模式是没有意义的。我还没有完成对该工具的静态分析器的所有结果的审查,但这个特殊情况是通过动态分析检测到的。无论如何,知道这不是事实上的资源泄漏是很好的,因为我怀疑使用BufferedInputStream包装InputStream(可能不关闭它)作为性能优化在公司已经是相当普遍的做法。