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

2022-09-01 00:05:08

为什么有必要或其子类?close()java.io.InputStream

现在,在写入文件后,如果我们不执行输出流,则我们打算写入文件中的数据将保留在缓冲区中,并且不会写入文件。java.io.OutputStreamFileOutputStreamclose()

因此,有必要对 .但是我从来没有有任何痛苦的经历,没有关闭一个.close()OutputStreamInputStream

但是,互联网和书籍上的所有文章都说,关闭任何Stream总是好的,可能是一个或一个.InputStreamOutputStream

所以我的问题是,为什么有必要?人们说你可能会面临记忆泄漏,不是吗。那么这是什么样的内存泄漏呢?close()InputStreamclose()


答案 1

InputStream占用了一个微小的内核资源,一个低级的文件句柄。此外,只要您打开文件进行读取,该文件就会在某种程度上被锁定(从删除,重命名)。让我们想象一下,您并不关心锁定的文件。最终,如果您需要读取另一个文件,并使用新的 InputStream 打开它,内核会按顺序为您分配一个新的描述符(文件流)。这最终会加起来。如果它是一个长时间运行的程序,那么程序失败只是时间问题。

处理器的文件描述符表通常大小有限。最终,文件句柄表将耗尽进程的可用插槽。即使在数千个中,对于长时间运行的应用程序,您仍然可以轻松耗尽此漏洞,此时,您的程序无法再打开新文件或套接字。

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

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

您从占用的 3 个插槽(STDIN、STDOUT、STDERR)开始。此外,任何网络套接字和其他类型的IPC都将使用同一表中的插槽。填写该代码后,您就对程序执行了拒绝服务。

所有这些都很高兴知道;如何最好地应用它?

如果你依靠本地对象来超出范围,那么它就取决于垃圾回收器,它可以在自己的甜蜜时刻(非确定性)收获它。不要依赖 GC,请显式关闭流。

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

对于 C#,等效的是实现 IDisposable 的对象上的“using”块。


答案 2

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


推荐