Stack Unwinding

When an exception is thrown but not caught in a particular scope, the method-call stack is "unwound," and an attempt is made to catch the exception in the next outer try block. This process is called stack unwinding. Unwinding the method-call stack means that the method in which the exception was not caught terminates, all local variables in that method go out of scope and control returns to the statement that originally invoked that method. If a TRy block encloses that statement, an attempt is made to catch the exception. If a try block does not enclose that statement, stack unwinding occurs again. If no catch block ever catches this exception and the exception is checked (as in the following example), compiling the program will result in an error. The program of demonstrates stack unwinding.

Example 13.6. Stack unwinding.

 1 // Example 13.6: UsingExceptions.java
 2 // Demonstration of stack unwinding.
 3
 4 public class UsingExceptions
 5 {
 6 public static void main( String args[] )
 7 {
 8 try // call throwException to demonstrate stack unwinding
 9 {
10 throwException();
11 } // end try
12 catch ( Exception exception ) // exception thrown in throwException
13 {
14 System.err.println( "Exception handled in main" );
15 } // end catch
16 } // end main
17
18 // throwException throws exception that is not caught in this method
19 public static void throwException() throws Exception
20 {
21 try // throw an exception and catch it in main
22 {
23 System.out.println( "Method throwException" );
24 throw new Exception(); // generate exception
25 } // end try
26 catch ( RuntimeException runtimeException ) // catch incorrect type
27 {
28 System.err.println(
29 "Exception handled in method throwException" );
30 } // end catch
31 finally // finally block always executes
32 {
33 System.err.println( "Finally is always executed" );
34 } // end finally
35 } // end method throwException
36 } // end class UsingExceptions

Method throwException
Finally is always executed
Exception handled in main


When method main executes, line 10 in the TRy block calls method throwException (lines 1935). In the try block of method throwException (lines 2125), line 24 throws an Exception. This terminates the try block immediately, and control skips the catch block at line 26, because the type being caught (RuntimeException) is not an exact match with the thrown type (Exception) and is not a superclass of it. Method throwException terminates (but not until its finally block executes) and returns control to line 10the point from which it was called in the program. Line 10 is in an enclosing try block. The exception has not yet been handled, so the try block terminates and an attempt is made to catch the exception at line 12. The type being caught (Exception) does match the thrown type. Consequently, the catch block processes the exception, and the program terminates at the end of main. If there were no matching catch blocks, a compilation error would occur. Remember that this is not always the casefor unchecked exceptions, the application will compile, but run with unexpected results.