为什么关闭()输入流是好的?

时间:2014-10-24 04:31:43

标签: java buffer inputstream outputstream

我在Java编程语言方面有丰富的经验。但是我一直想到的一件事是,为什么close() java.io.InputStream或其子类是必要的?

现在使用java.io.OutputStream,比如FileOutputStream,在写入文件之后,如果我们没有close()输出流,那么我们打算在文件中写入的数据保留在缓冲区中,不会写入文件。

因此有必要close() OutputStream。但是,在没有关闭 InputStream之后,我从未有过任何痛苦的经历。

但是,互联网和书籍上的所有文章仍然说关闭任何一个流可能总是好InputStreamOutputStream

所以我的问题是为什么close()InputStream有必要?人们说你可能会面临内存泄漏,而不是close()它。那是什么样的内存泄漏?

4 个答案:

答案 0 :(得分:35)

InputStream占用了一个微小的内核资源,一个低级文件句柄。此外,只要您打开文件进行读取,该文件将在某种程度上被锁定(从删除,重命名)。让我们想象你不关心锁定的文件。最后,如果您需要读取另一个文件,并使用新的InputStream打开它,内核会依次为您分配一个新的描述符(文件流)。这将加起来。

长时间运行应用程序的程序失败只是时间问题。

处理器的文件描述符表大小有限。最终,文件句柄表将耗尽进程的空闲插槽。即使在成千上万的情况下,您仍然可以轻松地将其用于长时间运行的应用程序,此时,您的程序将无法再打开新文件或套接字。

过程文件描述符表与以下内容一样简单:

IOHANDLE fds[2048];  // varies based on runtime, IO library, etc.

首先占用3个插槽。填写,你已经对自己进行了拒绝服务。

所以很高兴知道;如何最好地应用它?

如果依赖于本地对象超出范围,那么它可以直接使用垃圾收集器,垃圾收集器可以在自己的甜蜜时间(非确定性)中获取它。所以不要依赖GC,明确地关闭它们。

使用Java,您希望对实现java.lang.AutoCloseable的类型使用try-with-resources,“包括实现java.io.Closeable的所有对象”,每个文档:https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

使用C#,等价物是实现IDisposable

的对象上的“使用”块

答案 1 :(得分:7)

与文件句柄泄漏一样,它不是内存泄漏。操作系统只允许一个进程打开一定数量的文件,如果你不关闭输入流,它可能会禁止JVM再打开。

答案 2 :(得分:3)

潜在的资源泄漏。当你以这种方式提出问题时,继承使得无法准确知道可能泄漏的资源。例如,我可以编写自己的名为VoidInputStream的类,它不分配需要关闭的资源。但是如果你不关闭它,你仍然违反了继承的合同。

请参阅http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html以获取不同输入流的列表。

对泄露资源的测试非常困难。仅次于测试并发问题。不要太确定你在不知不觉中造成了一点点破坏。

答案 3 :(得分:2)

可能存在与InputStream关联的任意数量的OS资源,例如打开文件或套接字。 close()将释放这些资源。

您的程序不需要知道它正在使用哪种InputStream。它应该遵守使用后关闭流的合同,以便可以释放任何资源。