Java Return from Finally

March 18, 2011 - 2 minute read -
Java bugs exceptions

try...catch...finally is the common idiom in Java for exception handling and cleanup. The thing that people may not know is that returning from within a finally block has the unintended consequence of stoping an exception from propagating up the call stack. It "overrides" the throwing of an exception so that the caller will never get to handle it.

public class Main {
    public static void main(String[] args) throws Throwable {
        System.out.println("Starting");
        method();
        System.out.println("No way to know that an exception was thrown");
    }</p>
<p>    public static void method() throws Throwable {
        try {
            System.out.println("In method about to throw an exception.");
            throw new RuntimeException();
        } catch (Throwable ex) {
            System.out.println("Caught exception, maybe log it, and then rethrow it.");
            throw ex;
        } finally {
            System.out.println("return in finally prevents an exception from being passed up the call stack.");
            return; // remove the return to see the real behavior
        }
    }
}

I recently came across code like this. This is Real Bad. Returning from within finally prevents the propagation of regular exceptions, which is bad enough, but worse, prevents the propagation of runtime exceptions which are generally programmer errors. This one small mistake can hide programmer errors so that you'll never see them and never know why things aren't working as expected. One of the interesting things is that the Java compiler understands this as well. If you return from within a finally block where an exception would otherwise be thrown, the compiler does not force you to declare that exception in the method's throws declaration.

Long story short. Don't return from with finally. Ever.