Do unclosed streams cause memory leaks in java?

16,622

Solution 1

It's important to be precise in the use of the term 'memory leak' with respect to Java.

In Java, a memory leak happens when your code holds a reference permanently, so that some object is never garbage collected.

Failing to close a stream is not a memory leak in this sense. Streams that have native resources have finalizers; the GC will eventually close them down. Unless you hold a reference to the unclosed stream it isn't a leak.

However, there are other kinds of leaks besides memory leaks. Most operating systems limit the number of open files. If you fail to close your streams, the GC may take a very long time to close them for you; the net result may be that you run out of system file descriptors and your code fails to open one more file. Some people will call this a leak, but it's not accuracy to call it a memory leak.

Solution 2

(at least java 1.6 and earlier did had this problem).

ANY version of Java, and for that matter, ANY language, has this problem; it is not specific to Java.

If you get hold of an input or output handle which needs system resources, you need to release them no matter what.

Java has Closeable to signify that the instance you hold may, or may not, hold system resources; but in the event that it does, if you don't .close() it you'll leak resources; it's that simple.

For instance, you may have a method which has an InputStream as an argument; OK, fine, but what is this InputStream? Is it a FileInputStream or a ByteArrayInputStream, or even something else? You cannot know. The first needs to be closed properly but the second doesn't need to.

So what? .close() them all anyway, you have nothing to lose. Do you really want to take the chance?

With Java 6, you'll want to use Guava's Closer, since this is the safest way to have all your resources closed (and the JDK does not provide such a tool):

final Closer closer = Closer.create();

try {
    final InputStream in = closer.register(openInHere());
    final InputStream in2 = closer.register(...);
    final OutputStream out = closer.register(...);
    // do work with in, in2, out, other
} catch (WhateverException e) {
    // IF WhateverException is not an IOException and you want to rethrow...
    // throw closer.rethrow(e, WhateverException.class);
} finally {
    closer.close(); // always safe
}

With Java 7, you have try-with-resources which works with all AutoCloseable resources (which Closeable extends):

try (
    final InputStream in = ...;
    // etc
) {
    // work with AutoCloseable resources
} catch (WhateverException e) {
    // deal with e, rethrow if necessary
}

The main difference between Closer and try-with-resources is that with the latter, resources will be closed before catch whereas Closer will close them in finally.

But again: don't take a chance. Close them all.

Share:
16,622

Related videos on Youtube

BuzzLightYear
Author by

BuzzLightYear

Updated on July 08, 2022

Comments

  • BuzzLightYear
    BuzzLightYear almost 2 years

    I believe open streams cause memory leak in java (at least java 1.6 and earlier did had this problem).

    But, while searching (even here), I found some people agreeing with this while others do not. So, if I write this program:

    import java.io.*;
    public class CreatingMemoryLeak {
    
        public static void main(String args[])
        {
            String s = "xxxxxxx";
            InputStream in = new ByteArrayInputStream(ss.getBytes());
            BufferedInputStream bf = new BufferedInputStream(in);
    
            try {
                while(bf.read()>0)
                {
                    System.out.println("got it");
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("Here is a input stream " + s +" causing a memory leak");
    
        }
    }
    

    and if I do not close the bf stream explicitly, will it cause a memory leak?

    • Radiodef
      Radiodef about 10 years
      Note that usually the idea of close is to release native resources (such as C heap allocated data that needs to be deleted). The doc for ByteArrayInputStream specifically says close has no effect on it. So I do not think it's a good example of what you are actually asking here.