一次关闭Java中的所有流

Posted

技术标签:

【中文标题】一次关闭Java中的所有流【英文标题】:Closing all streams in Java at once 【发布时间】:2017-07-19 12:30:08 【问题描述】:

有没有办法在 Java 中一次关闭所有流或句柄而不引用它们?或者有没有办法关闭与特定文件关联的所有句柄(流)在 Java 中引用该文件?

【问题讨论】:

我的直觉反应是no, no way, not possible,但可能有一些特定于实现的方法来做到这一点......据我所知,没有与任何地方的文件关联的流的注册表在标准 API 中......为什么你需要这样做?您应该能够自己维护流的注册表...假设您在 some 点对每个流都有引用... 当然,杀死 JVM。 try-with-resources声明 即使有办法,也不要去做。只需在您的工作完成后立即关闭它们。 如果你有这个问题,你问错了问题。您需要找到并修复代码中可能引起此类问题的任何情况。 【参考方案1】:

没有

如果没有对流的引用,就无法在其上调用close(),与任何其他对象一样 - 如果没有对它的引用,您实际上无法对它做任何事情。我不完全确定流是如何在内部处理的,老实说,可能有一种方法可以使用内部或反射或 JNI 来做到这一点,但如果存在更好的解决方案,通常应该避免所有这些。

相反,您应该查看您的程序/代码的设计并尝试将其重新设计为:

    close() 使用后立即流式传输,或 自己维护开放流列表

如果您使用的 API 没有为您提供对流的引用,并且没有 close() 流,并且无法为您提供close() 流的方法,那么这是一个错误/您正在使用的 API 存在设计缺陷。

如果您在某一时刻有对流的引用,但丢失了该引用并需要稍后将其关闭,那么您可以简单地设置某种注册表来维护流列表。一个非常简单的例子是这样的:

public class StreamRegistry 
    private List<Closeable> streams = new ArrayList<>();

    public void register(Closeable closeable) 
        streams.add(closeable);
    

    public void close() throws IOException 
         for(Closeable closeable : streams) 
             closeable.close();
         
    
    

尽管您可能想从close() 中捕获IOException,但将其记录下来,然后继续尝试关闭流。

但是,除非绝对必要,否则我不建议使用注册表。正如@EJP 和@Suresh Atta 在cmets 中对您的问题所说,如果您提出此类问题,您可能应该尝试重构/重新设计您的代码以完全避免此问题,并尽快尝试close() 流就像你完成了他们一样。也就是说,在不确切知道您为什么需要这样做的情况下,除了提出选项之外,我真的无能为力。

【讨论】:

正如您在我的场景中提到的,我在自己的代码中使用了第 3 方代码,它创建了一些文件。从程序的行为来看,第 3 方代码似乎忘记在某个地方关闭流。我想我会使用一些代码分析器来分析第 3 方代码的内存泄漏。【参考方案2】:

最好的方法是使用一些静态代码分析工具,如声纳。它将告诉您关闭开放流时错过的地方在哪里。如果您忘记打开任何流,它会告诉您存在必须修复的阻止程序问题。

有关声纳的更多详细信息,您可以使用给定的链接。

Sonar Qube

【讨论】:

正如您在我的场景中提到的,我在自己的代码中使用了第 3 方代码,它创建了一些文件。从程序的行为来看,第 3 方代码似乎忘记在某个地方关闭流。我想我会使用一些代码分析器来分析第 3 方代码的内存泄漏。

以上是关于一次关闭Java中的所有流的主要内容,如果未能解决你的问题,请参考以下文章

wpf遍历文件夹获取所有图片路径后,怎么关闭图片流

Java中的IO字节流

java 输入输出流 一个类中只能使用一次吗? 流关闭后 就不能再打开吗?

java 输入输出流 一个类中只能使用一次吗? 流关闭后 就不能再打开吗?

java 字节流和字符流

Java 接口Closeable