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

Adi*_*ngh 34 java buffer inputstream outputstream

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

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

所以有必要close()OutputStream.但是,我从来没有过之后任何痛苦的经历不打烊InputStream.

但是,互联网和书籍上的所有文章仍然说关闭任何流可能是一个InputStream或一个OutputStream.

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

cod*_*eim 42

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

对于长时间运行的应用程序,程序失败只是时间问题.

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

进程文件描述符表就像下面这样简单:

IOHANDLE fds[2048];  // varies based on runtime, IO library, etc.
Run Code Online (Sandbox Code Playgroud)

你开始占用3个插槽.填写,你已经对自己进行了拒绝服务.

所以这一切都很好知道; 如何最好地应用它?

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

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

使用C#,等效项是实现IDisposable的对象上的"使用"块


chr*_*ke- 8

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


can*_*nge 5

这是潜在的资源泄漏。继承使您无法确切地知道以这种方式提出问题时可能泄漏哪些资源。例如,我可以编写自己的类VoidInputStream,该类不分配需要关闭的资源。但是,即使您不关闭它,也将违反继承的合同。

有关不同输入流的列表,请参见http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html

对泄漏的资源进行测试非常困难。仅次于并发问题测试。不要不确定您是否在不知不觉中造成了一点破坏。