Why is it good to close() an inputstream?

22,991

Solution 1

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.

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.

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.

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

With C#, the equivalent is a "using" block on objects that implement IDisposable

Solution 2

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.

Solution 3

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.

See http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html For a list of the different input streams.

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.

Solution 4

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

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.

Share:
22,991

Related videos on Youtube

Aditya Singh
Author by

Aditya Singh

I am a computer programmer, mobile phone programmer and a web developer, and a model :P.

Updated on July 09, 2022

Comments

  • Aditya Singh
    Aditya Singh almost 2 years

    Why is it necessary to close() java.io.InputStream or its subclasses?

    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.

    So it becomes necessary to close() an OutputStream. But i never had any bitter experiences after not closing an 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.

    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?

    • Andy
      Andy over 9 years
      resource-leak is probably more of a concern here. Handling inputstream requires OS to use its resources and if you don't free it up once you use it, you will eventually run out of resources.
    • mailmindlin
      mailmindlin over 9 years
      In some JVMs, the underlying kernel will keep a FIS open (as I undertand it) until you: A) close the stream or B) the JVM exits. Other streams (especially when dealing with sockets) let other stuff know when you are done. For example, when closing a OutStream from a Socket, the corresponding inputstream on the other side of the internet closes too.
    • user207421
      user207421 about 6 years
      @mailmindlin No it doesn't. No streams close automatically. You have to close them yourself.
    • Guido Flohr
      Guido Flohr over 5 years
      You don't have to close it for all subclasses. For example a java.io.ByteArrayInputStream does not use any file descriptors, and hence closing it is a no-op, see docs.oracle.com/javase/8/docs/api/java/io/…
  • Aditya Singh
    Aditya Singh over 9 years
    I am talking about an InputStream in general. And not just a FileInputStream.
  • Joachim Isaksson
    Joachim Isaksson over 9 years
    @Aditya Your original example with OutputStream uses a FileOutputStream to illustrate why it needs to be closed, so why would this be a less valid example? :)
  • Aditya Singh
    Aditya Singh over 9 years
    No, coz that was to make you understand my question. But this answer is specifically for a FileInputStream. While my question is for an InputStream in general. :)
  • user207421
    user207421 over 9 years
    So is the answer. Most streams ultimately consume an FD n the kernel. Whether that refers to a file, a socket, or something else, is completely irrelevant.
  • Aditya Singh
    Aditya Singh over 9 years
    What does an FD stand for?
  • user207421
    user207421 over 9 years
    @Aditya It stands for 'file descriptor', but that's a pretty general term in the kernel that's also used for sockets, communications ports, ...
  • pinkpanther
    pinkpanther over 7 years
    Is it closed when if it is local variable and method returns? Ofcourse assuming that we only have used ClassPathResource of spring.
  • codenheim
    codenheim about 6 years
    @pinkpanther - You'll need to use try-with-resources to ensure that, otherwise, its up to the Garbage Collector as to when it'll reap them (nondeterministic). docs.oracle.com/javase/tutorial/essential/exceptions/… -- Same applies in C# but you'd use the using statement.