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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26541513/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:06:39  来源:igfitidea点击:

Why is it good to close() an inputstream?

javabufferinputstreamoutputstream

提问by Aditya Singh

I have a sound experience in Java programming language. But one thing that has always been in my mind is that why is it necessary to close()java.io.InputStreamor its subclasses?

我在 Java 编程语言方面有丰富的经验。但是我一直在想的一件事是,为什么需要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. But i never had any bitter experiences after not closingan InputStream.

所以有必要close()OutputStream。但是在没有关闭一个InputStream.

But still all articles on the internet and books say that it is always good to close any Stream may it be an InputStreamor an OutputStream.

但是互联网上的所有文章和书籍仍然说关闭任何流总是好的,无论它是一个InputStream还是OutputStream.

So my question is that why does it become necessary to close()an InputStream? People say that you may face a memory leak of you don't close()it. So what kind of a memory leak is that?

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

回答by codenheim

An InputStream ties up a tiny kernel resource, a low level file handle. 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. This will eventually add up. If it is a long running program then it is just a matter of time until your program fails.

InputStream 占用了一个微小的内核资源,一个低级文件句柄。此外,文件将在一定程度上被锁定(从删除、重命名),只要您将其打开以供读取。假设您不关心锁定的文件。最终,如果您需要读取另一个文件,并使用新的 InputStream 打开它,内核会依次为您分配一个新的描述符(文件流)。这最终会加起来。如果它是一个长时间运行的程序,那么您的程序失败只是时间问题。

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). Also any network sockets and other types of IPC will use a slot in the same table. Fill that up and you have performed a denial of service on your program.

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

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 的对象上的“使用”块

回答by chrylis -cautiouslyoptimistic-

It's not a memoryleak 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 再打开。

回答by candied_orange

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. But still if you don't close it you're violating the inherited contract.

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

See http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.htmlFor 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.

众所周知,测试泄漏的资源非常困难。仅次于测试并发问题。不要太确定你没有在不知不觉中造成了一点破坏。

回答by Thomas Stets

There might be any number of OS resources associated with an InputStream, like open files, or Sockets. A close() will free these resources.

可能有任意数量的操作系统资源与 InputStream 相关联,例如打开的文件或套接字。close() 将释放这些资源。

Your program does not need to know what kind of InputStream it is working with. It just should adhere to the contract that the stream is closed after use, so that any resources may be released.

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