Tuesday, June 14, 2011

Java7 Automatic resource management

ARM:

One of the useful features in Java7 is the Automatic resource management via the try-with-resources statement.

In the olden days thou would (or atleast were supposed to) code like:
void doSomething() throws IOException {
  OutputStream out = null;
  try {
    out = new FileOutputStream("");
    out.write(data);
  } finally {
    if (out != null) {
      out.close();
    }
  }
}

Which is error prone if you do forget to close the resources.

The new way is:

void doSomethingNew() throws IOException {
  try (OutputStream out = new FileOutputStream("")) {
    out.write(data);
  }
}

This is syntactically much more pleasing and does the right thing internally.

Going deep:
The try-with syntax works with any AutoCloseable implementation and you can have multiple resources as well.

The compiler will transform the above code into something like:

void doSomethingNew() throws IOException {
  OutputStream out = null;
  Throwable localThrowable1 = null;
  try {
    out = new FileOutputStream("");
    out.write(blah);
  } catch (Throwable localThrowable2) {
    // We keep a reference to which can add a suppressed exception
    localThrowable1 = localThrowable2;
    throw localThrowable2;
  } finally {
    if (out != null) {
      if (localThrowable1 != null) {
        // Already have an exception thrown
        try {
          out.close();
        } catch (Throwable localThrowable3) {
          // Add the suppressed exception during close
          localThrowable1.addSuppressed(localThrowable3);
        }
      } else {
        // Potentially throw an IOException due to failure when close'ing
        out.close();
      }
    }
  }
}

The pattern is:

  • If there are no exception - close() in the finally block OR
  • If there are no exception during operation but there is an exception during close() then throw it OR
  • If there is an exception thrown then throw it after closing the resource OR
  • If there is an exception1 thrown then throw it .. and if there is an exception2 closing the resource.. then exception1.addSuppressed(exception2). This is new in theThrowable class

Sidenote:
There was a huge effort to get closures into Java7 but none of the solutions was light on syntax/complexity. After the backlash over Generics a smaller but better step has been taken.

Sidenote++:
For scala see using. You do not need to wait for language changes to make syntactically pleasing APIs because of curry-ing and other fancy stuff.


More References:
ARM spec
Article on ARM