Freeing java file handles

Jamie Cook picture Jamie Cook · Oct 22, 2009 · Viewed 18.5k times · Source

We have a rather large and complex application written in Java which is running on top of the Gridgain package. The problem I am having is that this application will sit there processing requests for approximately a day before every request starts resulting in an exception of type java.nio.channels.ClosedByInterruptException.

My supposition is that the application is not releasing file handles and after a day of continuous usage it runs out and can no longer continue to process requests (each request requires the reading of multiple files from each grid node). We have wrapped most of our file IO operations in classes such as this one

package com.vlc.edge;

import com.vlc.common.VlcRuntimeException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public final class BufferedReaderImpl implements BufferedReader {
    private java.io.BufferedReader reader;

    public BufferedReaderImpl(final String source) {
        this(new File(source));
    }

    public BufferedReaderImpl(final File source) {
        try {
            reader = new java.io.BufferedReader(new FileReader(source));
        } catch (FileNotFoundException e) {
            throw new VlcRuntimeException(e);
        }
    }

    public BufferedReaderImpl(final Reader reader) {
        this.reader = new java.io.BufferedReader(reader);
    }

    public String readLine() {
        try {
            return reader.readLine();
        } catch (IOException e) {
            throw new VlcRuntimeException(e);
        }
    }

    public void close() {
        try {
            reader.close();
        } catch (IOException e) {
            throw new VlcRuntimeException(e);
        }
    }
}

I think the problem is that this design doesn't explicitly release the file handle, my proposed solution is to add a finalize method like this

    protected void finalize() throws Throwable
    {
        reader.close();
        super.finalize();   
    }

which will do this explicitly. The question (finally) is whether or not this is likely to have any effect. Do classes such as java.io.BufferedReader already have some mechanism for dealing with this type of problem?

EDIT: Also greatly appreciated here would be ways of checking whether this is actually the problem... ie is there a way to query a running JVM and ask about it's file handle allocations?

Answer

cletus picture cletus · Oct 22, 2009

Finalizers can't be relied on to be called. It's not a good approach for resource management. The standard construct in Java for this is:

InputStream in = null;
try {
  in = ...;
  // do stuff
} catch (IOException e) {
  // error
} finally {
  if (in != null) { try { in.close(); } catch (Exception e) { } }
  in = null;
}

You may want to wrap these handles inside a class but that's not a robust approach.