Does a finally block always get executed in Java? – Dev

The best answers to the question “Does a finally block always get executed in Java?” in the category Dev.

QUESTION:

Considering this code, can I be absolutely sure that the finally block always executes, no matter what something() is?

try {  
    something();  
    return success;  
}  
catch (Exception e) {   
    return failure;  
}  
finally {  
    System.out.println("I don't know if this will get printed out");
}

ANSWER:

Example code:

public static void main(String[] args) {
    System.out.println(Test.test());
}

public static int test() {
    try {
        return 0;
    }
    finally {
        System.out.println("something is printed");
    }
}

Output:

something is printed. 
0

ANSWER:

Yes, finally will be called after the execution of the try or catch code blocks.

The only times finally won’t be called are:

  1. If you invoke System.exit()
  2. If you invoke Runtime.getRuntime().halt(exitStatus)
  3. If the JVM crashes first
  4. If the JVM reaches an infinite loop (or some other non-interruptable, non-terminating statement) in the try or catch block
  5. If the OS forcibly terminates the JVM process; e.g., kill -9 <pid> on UNIX
  6. If the host system dies; e.g., power failure, hardware error, OS panic, et cetera
  7. If the finally block is going to be executed by a daemon thread and all other non-daemon threads exit before finally is called

ANSWER:

Here’s the official words from the Java Language Specification.

14.20.2. Execution of try-finally and try-catch-finally

A try statement with a finally block is executed by first executing the try block. Then there is a choice:

  • If execution of the try block completes normally, […]
  • If execution of the try block completes abruptly because of a throw of a value V, […]
  • If execution of the try block completes abruptly for any other reason R, then the finally block is executed. Then there is a choice:
    • If the finally block completes normally, then the try statement completes abruptly for reason R.
    • If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).

The specification for return actually makes this explicit:

JLS 14.17 The return Statement

ReturnStatement:
     return Expression(opt) ;

A return statement with no Expression attempts to transfer control to the invoker of the method or constructor that contains it.

A return statement with an Expression attempts to transfer control to the invoker of the method that contains it; the value of the Expression becomes the value of the method invocation.

The preceding descriptions say “attempts to transfer control” rather than just “transfers control” because if there are any try statements within the method or constructor whose try blocks contain the return statement, then any finally clauses of those try statements will be executed, in order, innermost to outermost, before control is transferred to the invoker of the method or constructor. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a return statement.

ANSWER:

Also, although it’s bad practice, if there is a return statement within the finally block, it will trump any other return from the regular block. That is, the following block would return false:

try { return true; } finally { return false; }

Same thing with throwing exceptions from the finally block.