一次关闭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中的所有流的主要内容,如果未能解决你的问题,请参考以下文章
java 输入输出流 一个类中只能使用一次吗? 流关闭后 就不能再打开吗?