11.3 Handling of an Exception

When an exception is thrown, control is transferred from the code that caused the exception to the nearest dynamically-enclosing catch clause of a try statement (§14.18) that handles the exception.

A statement or expression is dynamically enclosed by a catch clause if it appears within the try block of the try statement of which the catch clause is a part, or if the caller of the statement or expression is dynamically enclosed by the catch clause.

The caller of a statement or expression depends on where it occurs:

  • If within a method, then the caller is the method invocation expression (§15.11) that was executed to cause the method to be invoked.
  • If within a constructor or the initializer for an instance variable, then the caller is the class instance creation expression (§15.8) or the method invocation of newInstance that was executed to cause an object to be created.
  • If within a static initializer or an initializer for a static variable, then the caller is the expression that used the class or interface so as to cause it to be initialized.

Whether a particular catch clause handles an exception is determined by comparing the class of the object that was thrown to the declared type of the parameter of the catch clause. The catch clause handles the exception if the type of its parameter is the class of the exception or a superclass of the class of the exception. Equivalently, a catch clause will catch any exception object that is an instanceof(§15.19.2) the declared parameter type.

The control transfer that occurs when an exception is thrown causes abrupt completion of expressions (§15.5) and statements (§14.1) until a catch clause is encountered that can handle the exception; execution then continues by executing the block of that catch clause. The code that caused the exception is never resumed.

If no catch clause handling an exception can be found, then the current thread (the thread that encountered the exception) is terminated, but only after all finally clauses have been executed and the method uncaughtException(§20.21.31) has been invoked for the ThreadGroup that is the parent of the current thread.

In situations where it is desirable to ensure that one block of code is always executed after another, even if that other block of code completes abruptly, a try statement with a finally clause (§14.18.2) may be used. If a try or catch block in a try-finally or try-catch-finally statement completes abruptly, then the finally clause is executed during propagation of the exception, even if no matching catch clause is ultimately found. If a finally clause is executed because of abrupt completion of a try block and the finally clause itself completes abruptly, then the reason for the abrupt completion of the try block is discarded and the new reason for abrupt completion is propagated from there.

The exact rules for abrupt completion and for the catching of exceptions are specified in detail with the specification of each statement in §14 and for expressions in §15 (especially §15.5).