NeuroAgent

Does Finally Block Always Execute in Java?

Learn why finally blocks in Java always execute even with return statements. Understand the exceptions and best practices for reliable resource cleanup in your Java code.

Question

Does a finally block always get executed in Java?

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

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

A finally block in Java will always execute if it’s reachable, even when there are return statements in the try or catch blocks. In your code example, the finally block will indeed print to the console regardless of whether something() completes normally or throws an exception, because the finally block executes before any return statement is completed.

Contents

Understanding Finally Block Execution

The finally block in Java is designed to provide a mechanism for executing code that must run regardless of whether an exception occurs or not. This is particularly useful for resource cleanup operations like closing database connections, file handles, or releasing other system resources.

The Java Language Specification mandates that a finally block is executed if it is reachable. In your code example, the finally block will always execute because there are no conditions that would prevent it from being reached. The only scenarios where a finally block might not execute are:

  • The JVM terminates abruptly (such as with System.exit())
  • The JVM crashes
  • The thread executing the code is killed
  • There’s an infinite loop that prevents the finally block from being reached

Return Statements and Finally Blocks

When a return statement is encountered in a try block, the JVM doesn’t immediately return. Instead, it executes the finally block before completing the return operation. This means that in your code:

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

The sequence of execution would be:

  1. something() is called
  2. If something() completes normally, the JVM prepares to return success, but first executes the finally block
  3. If something() throws an exception, the catch block executes, prepares to return failure, but first executes the finally block

Important Note: The return value is determined before the finally block executes, but the actual return happens after the finally block completes.

Exception Scenarios

The finally block behavior is consistent across different exception scenarios:

  1. Normal execution: When no exception occurs, the finally block executes before the return statement
  2. Exception caught: When an exception is caught by the catch block, the finally block executes before the catch block’s return statement
  3. Exception not caught: If the exception is not caught by this try-catch block, the finally block still executes before the exception propagates up the call stack
java
try {  
    something();  
    return success;  
}  
catch (RuntimeException e) {   
    return failure;  
}  
catch (Exception e) {   
    return otherFailure;  
}  
finally {  
    System.out.println("This always prints");
}

In this more complex example, the finally block would execute regardless of which catch block handles the exception, or if no exception occurs.

Edge Cases and Limitations

While finally blocks are very reliable, there are some edge cases to be aware of:

System.exit() Considerations

When System.exit() is called, the JVM begins shutdown procedures. If called from within a try or finally block, the finally block may not complete execution if the shutdown is too abrupt.

java
try {
    System.exit(0);
} finally {
    System.out.println("This may not print");
}

Infinite Loops

If there’s an infinite loop in the try block that never completes, the finally block will never be reached:

java
try {
    while(true) {
        // infinite loop
    }
} finally {
    System.out.println("This will never execute");
}

Thread Termination

If the executing thread is terminated abruptly (using Thread.stop() which is deprecated), the finally block may not execute.

Best Practices

When using finally blocks, consider these best practices:

  1. Keep finally blocks simple: Avoid complex logic or operations that might throw exceptions
  2. Use for resource cleanup: Finally blocks are ideal for closing resources like database connections, file streams, and network sockets
  3. Avoid return statements in finally blocks: This can make code flow difficult to understand and may hide exceptions
  4. Consider try-with-resources: For resources that implement AutoCloseable, prefer try-with-resources syntax over finally blocks

Practical Examples

Resource Management Example

java
FileInputStream fis = null;
try {
    fis = new FileInputStream("test.txt");
    // process file
} catch (IOException e) {
    // handle exception
} finally {
    if (fis != null) {
        try {
            fis.close();
        } catch (IOException e) {
            // handle close exception
        }
    }
}

Method Return Example

java
public String processData() {
    try {
        // complex processing
        return "Success";
    } catch (Exception e) {
        return "Failed";
    } finally {
        // cleanup operations
        System.out.println("Processing complete");
    }
}

In this method, regardless of whether the processing succeeds or fails, the “Processing complete” message will always be printed, and the appropriate return value (“Success” or “Failed”) will be returned.

Sources

  1. Java Language Specification - The try Statement
  2. Oracle Java Tutorials - The try Statement
  3. Effective Java - Item 9: Prefer try-with-resources to try-finally

Conclusion

  • The finally block in your code example will always execute if it’s reachable, which it is in this case
  • Return statements in try or catch blocks do not prevent finally block execution - the finally block runs before the return is completed
  • Finally blocks are essential for proper resource management and cleanup operations
  • While finally blocks are very reliable, they have some edge cases where they might not execute, such as with System.exit() or infinite loops
  • For modern Java development, consider using try-with-resources for resource management instead of traditional finally blocks where appropriate

You can be absolutely sure that in your specific code example, the finally block will execute and print to the console, regardless of what something() does, as long as the JVM continues running normally.