Java Filehandle GC

Relay was leaking file handles in a bad way. In a crashy way. Getting rid of the last occurance right now.

Relay has it’s own URI resolver, since the Java URI resolver to both too complex, and not flexible enough.

Too complex is self-evident. Many things there I don’t need, and do not want to implement. Not flexible in that if you want to specify a custom protocol, it must be for your entire application. If I’m misaken, please let me know.

Relay does dependency management. Relay gets it’s resources through URIs. You’d expect to see some of this…

if (lastModified == 0L || checkDirty)
{
    URL res = getServletContext().getResource(pathToRes);
    URLConnection connection = team.openConnection();

    if (connection.getLastModified() > lastModified)
    {
        doSomething(connection);
    }
}

If the resource is a file resource, an input stream is opened, for some strange reason, when you ask for the connection. (You can watch this happen in the debugger.)

Now a file stream is open. If the file is not modified, the file steam is not used, and thus, it is not closed. Not until garbage collection calls the finalize method of the file stream object.

When I give my servlet engine a lot of memory, I run out of file handles long before I run out of memory. IO exceptions are thrown, but garbage collection is not triggered, so those file handles are not released. Not without restarting the servlet engine.

Best of all, there’s no close method on the connection. You have to ask for the input stream, and close that.

This runs counter to my intuition. To I thought I’d blog it out.

If you are using URI’s in Java, checking modified dates, and leaking file handles, keep this in mind.

Leave a Reply