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

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

【问题讨论】:

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

标签: java file stream handles


【解决方案1】:

没有

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

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

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

如果您使用的 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 方代码的内存泄漏。
猜你喜欢
  • 2013-05-11
  • 2011-05-24
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
  • 1970-01-01
相关资源
最近更新 更多