Monday 6 April 2009

Java Resource Handling: Java 7

So, how does all this fit in with the proposals for solving this problem for Java 7?

ARM (Automatic Resource Management)

This proposal for Java 7 by Joshua Bloch, is for a slightly enhanced version of C#s "using" statement, enhanced by allowing support for multiple resources in a single declaration without nesting, e.g. my alternative #2 above:

void foo() throws IOException {
    Closer closer = new Closer();//the new helper class
    SomeResource r1=null;
    SomeResource r2=null;
    try {
        //create and use r1 & r2
        closer.completed();
    }
    finally {
        closer.close(r2,r1);
    }
}

becomes:

void foo() throws IOException {
    do (SomeResource r1=null;
    SomeResource r2=null;) {
        //create and use r1 & r2
    }
}

(though, obviously, in either example you might create r1&r2 where they are declared). The advantages of alternative #2 all apply to ARM, and porting from this pattern to this Java 7 construct would be trivial.

BGGA

The big rival approach is BGGA Closures, which give handling close() as a prime example:

with(FileReader in : makeReader()) with(FileWriter out : makeWriter()) {
    // code using in and out
}

(where with() is a framework API). This example neatly shows the power of the proposal (no need for an extension specifically for handling close(), ability to change how exceptions thrown by close() are handled), it also shows how the code becomes more complex. Like adding templates to a language I need to spend hours reading the spec and playing with example code before I can become proficient, and still it is liable to obfuscation (what a wonderfully self-unaware word that is!).

Thoughts

Neither proposal solves the underlying problems - restricted lifetime objects as per C++ is an elegant solution that (like the baby with the bathwater) has been thrown out along with explicit memory management, to the language's detriment. It would be far from easy to retrofit this.

Secondly, neither proposal fixes close() - it is not necessary for this API to throw exceptions - the exceptions it throws should be limited to those associated with flushing the final writes, and so there should be a flush() call (that can throw) which you call before close() (which cannot), hence moving close() to finally.
In fact, both proposals side-step this problem, with ARM leaving it as an open issue, and BGGA leaving it up to you!

Let's face it though - neither you nor I are likely to be influencing the choice for Java 7 - so the key thing is to write your code so that it is clear, robust, and capable of porting to whatever proposal is implemented. Both of my recommended approaches do that, and the choice is yours. 

No comments:

Post a Comment