简体   繁体   English

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

[英]Why is it good to close() an inputstream?

Why is it necessary to close() java.io.InputStream or its subclasses?为什么需要close() java.io.InputStream或其子类?

Now with java.io.OutputStream , say FileOutputStream , after writing to a file, if we don't close() the output stream, the data that we intended to write in the file remains in the buffer and is not written to the file.现在使用java.io.OutputStream ,比如FileOutputStream ,在写入文件后,如果我们不close()输出流,我们打算写入文件的数据将保留在缓冲区中,不会写入文件.

So it becomes necessary to close() an OutputStream .所以有必要close()一个OutputStream But i never had any bitter experiences after not closing an InputStream .但是在没有关闭InputStream之后,我从未有过任何痛苦的经历。

But still all articles on the internet and books say that it is always good to close any Stream may it be an InputStream or an OutputStream .但是互联网上的所有文章和书籍仍然说关闭任何 Stream 总是好的,无论它是InputStream还是OutputStream

So my question is that why does it become necessary to close() an InputStream ?所以我的问题是为什么有必要close()一个InputStream People say that you may face a memory leak of you don't close() it.人们说你可能会面临内存泄漏,因为你没有close()它。 So what kind of a memory leak is that?那么这是一种什么样的内存泄漏呢?

An InputStream ties up a tiny kernel resource, a low level file handle. InputStream 占用了一个微小的内核资源,一个低级文件句柄。 In addition, the file will be locked to some extent (from delete, renaming), as long as you have it open for read.此外,文件将在一定程度上被锁定(从删除、重命名),只要您将其打开以供读取。 Lets imagine you didn't care about the locked file.假设您不关心锁定的文件。 Eventually, if you need to read another file, and open it with a new InputStream, the kernel sequentially allocates a new descriptor (file stream) for you.最终,如果您需要读取另一个文件,并使用新的 InputStream 打开它,内核会依次为您分配一个新的描述符(文件流)。 This will eventually add up.这最终会加起来。 If it is a long running program then it is just a matter of time until your program fails.如果它是一个长时间运行的程序,那么您的程序失败只是时间问题。

The file descriptor table for a processor is typically of limited size.处理器的文件描述符表通常大小有限。 Eventually the file handle table will run out of free slots for the process.最终,文件句柄表将耗尽进程的空闲插槽。 Even in the thousands, you can still easily exhaust this for a long running application, at which point, your program can no longer open a new file or socket.即使在数千个中,您仍然可以轻松地为长时间运行的应用程序耗尽它,此时,您的程序将无法再打开新文件或套接字。

The process file descriptor table is as simplistic as something like:进程文件描述符表非常简单,如下所示:

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

You start with 3 slots occupied (STDIN, STDOUT, STDERR).您从占用的 3 个插槽开始(STDIN、STDOUT、STDERR)。 Also any network sockets and other types of IPC will use a slot in the same table.此外,任何网络套接字和其他类型的 IPC 都将使用同一个表中的插槽。 Fill that up and you have performed a denial of service on your program.填写它,您已经对您的程序执行了拒绝服务。

All that is nice to know;很高兴知道所有这些; how best to apply it?如何最好地应用它?

If you rely on local objects to go out of scope, then its up to the Garbage Collector, which can reap it in its own sweet time (nondeterministic).如果您依赖本地对象超出范围,则取决于垃圾收集器,它可以在自己的甜蜜时间(不确定)中收获它。 Don't rely on the GC, close the streams explicitly.不要依赖 GC,明确关闭流。

With Java, you want to use try-with-resources on types that implement java.lang.AutoCloseable, "which includes all objects which implement java.io.Closeable" per the docs: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html对于 Java,您希望在实现 java.lang.AutoCloseable 的类型上使用 try-with-resources,“其中包括实现 java.io.Closeable 的所有对象”,每个文档: https : //docs.oracle.com/javase /tutorial/essential/exceptions/tryResourceClose.html

With C#, the equivalent is a "using" block on objects that implement IDisposable使用 C#,等效的是在实现 IDisposable 的对象上的“使用”块

It's not a memory leak as much as a file-handle leak.它不像文件句柄泄漏那样是内存泄漏。 The operating system will only allow a single process to open a certain number of files, and if you don't close your input streams, it might forbid the JVM from opening any more.操作系统只允许一个进程打开一定数量的文件,如果你不关闭你的输入流,它可能会禁止 JVM 再打开。

It's a potential resource leak.这是潜在的资源泄漏。 Inheritance makes it impossible to know exactly what resource could be leaked when you ask the question this way.当您以这种方式提问时,继承使得无法确切知道哪些资源可能被泄露。 For example I could write my own class called VoidInputStream that allocates no resources that require closing.例如,我可以编写自己的名为 VoidInputStream 的类,该类不分配需要关闭的资源。 But still if you don't close it you're violating the inherited contract.但是如果你不关闭它,你仍然违反了继承的合同。

See http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html For a list of the different input streams.有关不同输入流的列表,请参见http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html

Testing for leaked resources is notoriously difficult.测试泄漏的资源是出了名的困难。 Second only to testing for concurrency issues.仅次于测试并发问题。 Don't be so sure you haven't unknowingly caused a little havoc.不要太确定你没有在不知不觉中造成了一点破坏。

There might be any number of OS resources associated with an InputStream, like open files, or Sockets.可能有任意数量的操作系统资源与 InputStream 相关联,例如打开的文件或套接字。 A close() will free these resources. close() 将释放这些资源。

Your program does not need to know what kind of InputStream it is working with.您的程序不需要知道它正在使用哪种 InputStream。 It just should adhere to the contract that the stream is closed after use, so that any resources may be released.只需遵守使用后关闭流的约定,以便释放任何资源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM