Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resource leak: 'in' is never closed, though it IS closed

Tags:

java

java-io

I know that there are a couple of similarly entitled questions out there, but most of them have simply forgotten to put a close() directive on their stream. This here is different.

Lets say I have the following minimal example:

public void test() throws IOException
{
    InputStream in;
    if( file.exists() )
    {
        in = new FileInputStream( file );
    }
    else
    {
        in = new URL( "some url" ).openStream();
    }
    in.close();
}

This give me a Resource leak: 'in' is never closed warning in Eclipse (Juno SR1). But when I move the in.close() into the conditional block, the warnings vanishes:

public void test() throws IOException
{
    InputStream in;
    if( file.exists() )
    {
        in = new GZIPInputStream( new FileInputStream( file ) );
        in.close();
    }
    else
    {
        in = new URL( "some URL" ).openStream();
    }
}

What is going on here?

like image 546
theV0ID Avatar asked Jan 10 '13 10:01

theV0ID


People also ask

What is resource leak is never closed?

A resource leak occurs when you don't close a reader, scanner, buffer, or another process that uses resources and needs to clean them up out of memory. You would call scanner. close() after you use the Scanner for whatever you're doing with it.

What is meant by resource leak?

Resource leaks are bugs that arise when a program doesn't release the resources it has acquired. Resource leaks can lead to resource exhaustion. In the worst case, they can cause the system to slow down or even crash. Starting with Java 7, most classes holding resources implement the java.

What does resource leak in Java mean?

In computer science, a resource leak is a particular type of resource consumption by a computer program where the program does not release resources it has acquired. This condition is normally the result of a bug in a program.


1 Answers

Because of the IO exception, you can run into a resource leak (poentially)

Try doing the following:

public void test() throws IOException
{
    InputStream in= null;
    try {
        if( file.exists() )
        {
            // In this case, if the FileInputStream call does not
            // throw a FileNotFoundException (descendant of IOException)
            // it will create the input stream which you are wrapping
            // in a GZIPInputStream (no IO exception on construction)
            in = new GZIPInputStream( new FileInputStream( file ) );
        }
        else
        {
            // Here however, if you are able to create the URL
            // object, "some url" is a valid URL, when you call
            // openStream() you have the potential of creating
            // the input stream. new URL(String spec) will throw
            // a MalformedURLException which is also a descendant of
            // IOException.
            in = new URL( "some url" ).openStream();
        }

        // Do work on the 'in' here 
    } finally {
        if( null != in ) {
            try 
            {
                in.close();
            } catch(IOException ex) {
                // log or fail if you like
            }
        }
    }
}

Doing the above will make sure you've closed the stream or at least made a best effort to do so.

In your original code, you had the InputStream declared but never initialized. That is bad form to begin with. Initialize that to null as I illustrated above. My feeling, and I'm not running Juno at the moment, is that it sees that the InputStream 'in', may potentially make it through all the hoops and hurdles to get to the point at which you are going to use it. Unfortunate, as someone pointed out, your code is a bit dodgy for an example. Doing this as I've detailed as well as @duffymo you'll get rid of the warning.

like image 101
Dave G Avatar answered Oct 30 '22 15:10

Dave G