Tuesday 31 March 2009

Resource Leak Anti-Patterns in Java

Guarding against resource leaks in Java is fraught with peril. I've seen the following three well-known anti-patterns used by experienced Java developers, so it's well worth starting any discussion on the correct way to manage resources by restating how not to do it!

Anti-Pattern #1: Close resources in your finalizer

You put all your resources as member variables of a class, and then close them in the finalizer, just as if it were a C++ destructor.
The fundamental problem with this approach is that finalizers are only called when the VM is freeing up memory, so you're hoping that the system runs out of a plentiful resource (memory) before it runs out of a scarce resource.
Regardless of what cludges you attempt (you were hoping that System.gc() or System.runFinalization() might help out weren't you?) this approach is fatally flawed from the outset.

Anti-Pattern #2: Mishandling multiple calls to close()

The standard Java approach is to put your resource handling code in a try block, and the resource closing in a finally block.

void foo() throws IOException {
SomeResource r1;
AnotherResource r2;
try {
//open r1 & r2 and do some other stuff that might throw an exception
}
finally {
r2.close();
r1.close();
}
}

However, close() can throw an exception, and if r2.close() throws an exception, then r1 will never get closed...

Anti-Pattern #3: Supressing close() exceptions

It's bad form to throw exceptions in a finally clause since it both masks any exception thrown in the try block and also causes the rest of the finally clause not to run, so you often see the following solution:

void foo() throws IOException {
SomeResource r = new SomeResource();
try {
//do some stuff with r
}
finally {
try{ r.close(); } catch(IOException e) { /*swallow e silently*/ }
}
}


Normally this works nicely - until close() throws an exception after the try block has been succesful, which causes the error to be silently ignored!

This leads to the worse class of defect (as per my last post) - one that easily goes undetected until it causes a failure in the real world, and also one that is very difficult to track down.

No comments:

Post a Comment