Tuesday, October 07, 2008

Finally-close your resources

You are a java programmer. Do you read from databases? Perhaps you write to files? If you aren't careful, you might be creating memory leaks and inadvertently leaving database connections open. Java is notorious for making simple things like file i/o complicated. Consider the try-catch block inside the finally block, which is necessary because the close() method throws an IOException; what is an application programmer supposed to do if the operating system won't allow him to close an open file? Witness the following code:

1 myFile.open();
2 contents = myFile.readContents();
3 myFile.close();
If an exception occurs while reading the file's contents on line 2, your program will skip over line 3 where the file is closed, as the exception interrupts normal execution flow and propagates up the stack, leaving the file ambiguously open. Fortunately, you can invoke this simple solution. Behold:
1 File file = new
File("/shared/home/richard.green/.bashrc");
2 BufferedReader reader = null;
try {
reader = new BufferedReader( new FileReader(file) );
String line = reader.readLine();
// Deal with line
}
catch (IOException e){
// Deal with exception ...
}
finally {
try {
reader.close();
} catch (IOException e) { /* ignored */ }
}
When execution leaves the try block (line 3), code inside the finally block (line 5) is executed under any circumstance. Therefore, in the above solution, if an exception occurs while reading the file's contents on line 3, the file will still be closed on line 5 before the exception propagates up the stack.

Frameworks like Commons IO from the Apache group ( http://commons/apache.org/io) take much of the pain out of dealing with Java I/O. Commons IO provides variety of utility classes which safely implement common I/O operations without dealing with the ugly Java Reader/Stream/Exception semantics.

Resource leaks due to exceptions are a problem in more-or-less every programming language. Each language has its own idioms for dealing with them. C++ coders wrap resources in their own classes and use the language's constructor-destructor semantics to allocate and de-allocate the resource. In Ruby, you use the IO::open method with a block; this automatically closes the resource when the block ends. Familiarize yourself with these idioms as part of learning a new language.

No comments: