Rekha Rekha - 6 months ago 17
Java Question

Behaviour of try-catch-finally block when exceptions are thrown from both try and finally block?

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}


if the methods readLine and close both throw exceptions, then the method readFirstLineFromFileWithFinallyBlock throws the exception thrown from the finally block; the exception thrown from the try block is suppressed. Why is the behaviour as such? Why is the exception from try block supressed?

Answer

Only exceptions within the try portion will be handled. Anything outside this (including the finally section isn't covered by a try and as such, Exceptions aren't handled.

If you want to catch/suppress the exception inside the finally block, you need to wrap if (br != null) br.close(); with it's own try/catch block, like this:

...
} finally {
  try {
    if (br != null) br.close();
  } catch (Exception e) {
    // whatever handling
  }
}
...

Also, the exception from the try block is suppressed because that's the behavior of a try block - to try something and give you a chance to recover. Since you don't catch any exceptions after your try block, no code is run in response to it.

Then, whether or not any exception is thrown, the finally block is executed. If it throws an exception, and because it's not inside a try/catch block of its own, its Exception is propagated out the method, and to the calling method.

To take the example from your comment below, as of Java 7, you'll want to refer to the documentation outlined here, and focus on the second-to-last section entitled "Supressed Exceptions", which basically says that multiple exceptions can be thrown out of a try block, up to one exception per declared resource.

As far as what happens if the resource declaration itself throws an exception, I don't have JDK7 installed, so I'm not sure. Why not put the following code in a test project (exactly as it appears, with a bogus path), see what happens, and then tell us what the result it for everyone's benefit:

try (BufferedReader br = new BufferedReader(new FileReader("a totally invalid path"))) {
  return br.readLine();
}