The labs on this site need JavaScript to run. The same content is written out below.
Learn › Java › Exceptions
Exceptions and finally
When an exception is thrown, which blocks run, and in what order?
When an exception is thrown in the try block, control jumps to the catch block, and the finally block runs whether the try block is left normally, by a return, or by an exception. The order is easy to get wrong when a return is involved or when another exception is thrown inside the catch block.
Checked against real execution · All 32 combinations were run on JDK 21 and checked against the results
Concepts in this lab
- finally and try-with-resources
- A finally block runs whether the try block ends normally or throws an exception (except when the JVM exits during the try, for example through System.exit()), and it is used to clean up resources. The try-with-resources statement lets you declare a resource that implements AutoCloseable inside the parentheses of try, and close() is then called automatically when the block ends. Compared with closing the resource yourself in finally, it leads to fewer forgotten closes and fewer exception-handling mistakes.
- Exception and Error
- Both are subtypes of Throwable that represent abnormal situations while a program runs. An Exception is a situation that the application can catch and handle (such as invalid input or a missing file). An Error is a serious problem at the JVM level, such as running out of memory or a stack overflow, and applications usually do not try to recover from it.
- Checked and unchecked exceptions
- Unchecked exceptions are RuntimeException and its subclasses (in the specification, the Error classes are also unchecked), and the compiler does not check whether they are handled (examples are NullPointerException and IllegalArgumentException). Checked exceptions are all other Exception classes, and the code compiles only if they are handled with catch or declared with throws (examples are IOException and SQLException). By default, Spring's @Transactional rolls back only on RuntimeException and Error, and commits on checked exceptions.
Try these
- Default settings — The catch block catches the exception thrown in the try block.
- An exception that the catch block does not catch — The catch block is skipped, but the finally block runs.
- A return in the try block — Even after the return value is set, the finally block runs first.
- A return in the finally block — The exception that was on its way out disappears.
- try-with-resources — The resource is closed before the catch and finally blocks run.
- Another exception inside catch — The new exception leaves the method, and the finally block runs before that.
Running with the default settings
- "try start" is printed, and then an IllegalArgumentException is thrown. The remaining lines of the try block ("try end") do not run.
- The type of the exception matches the IllegalArgumentException of the catch block. The catch block runs, and the exception is considered handled.
- The finally block runs.
- The try-catch-finally ends, and the line after it runs. "after the block" is printed, and 2 is returned.
Result of this run
- The finally block runs in every case: normal completion, a return, or an exception. That is why releasing locks and cleaning up resources are placed in the finally block.
Code
int run() {
try {
print("try start");
if (fail) throw new IllegalArgumentException(); // fail is true
print("try end");
} catch (IllegalArgumentException e) {
print("catch");
} finally {
print("finally");
}
print("after the block");
return 2;
}
Assumptions of this model
For all 32 combinations, the code exactly as shown (with only a fail field set to true, print, and Resource added) was compiled and run on JDK 21 on this PC, and the output order and the final result were checked (verify/plain/exflow_code_check.js). Only the case with one resource is covered. When there are several resources, they are closed in the opposite order from the order in which they were opened, and an exception thrown by close() is attached to the original exception as a suppressed exception.
Previous lab: Optional · Next lab: Checked and unchecked exceptions