The Java Termination Model
The Java exception handling facility supports the termination model. In the termination model, when a method encounters an exception, further processing in that method is terminated and control is transferred to the nearest exception handler that can handle the type of exception encountered. It’s important to note that this doesn’t necessarily mean the entire program is terminated. It depends on what action the exception handler performs and where the exception handler is in the call chain. For example, the program in Listing 1 continues even after an exception has been thrown.
Listing 1 Sample exception processing in which part of the program continues to execute.
... class simple_exception extends Exception{ int Value; public simple_exception() { Value = -1; } public simple_exception (String Desc) { super(Desc); } } public class example1 { example1(){} public boolean a() throws simple_exception { if(exceptional_condition){ simple_exception SimpleException = new simple_exception(); throw SimpleException; } // more processing for a() return(true); } public void b() { boolean Result; try{ Result = a(); // more processing ... } catch(simple_exception SomeException) { // execute exception handling strategy } finally{ // regardless to what happens the code in this // finally block is executed... ... // more recovery & cleanup code } } public void c() { // important processing } public static void main(String[] Args) { ... example1 Example1 = new example1(); Example1.b(); Example1.c(); .... } }
In the program in Listing 1, the method a() encountered an exceptional condition and was unable to continue its processing. The method b() called a(). Because a() threw an exception, b() was also unable to finish its processing. However, b() contains an exception handler that knows how to deal with simple_exception objects. So when a() throws the exception, b()’s handler is activated. b()’s exception handler uses some strategy to cause the program to be stabilized. Ideally, b()’s exception handler will bring the software back into a consistent state. Another important component to notice in b() is the finally{} block. Even if the code in a method is interrupted abruptly by an exception, the system will attempt to implement the finally block.
In Example1, b()’s processing is interrupted because a() throws an exception. b() contains an exception handler that handles the problem encountered in a(). Although b()’s regular flow of control is interrupted, the exception handler executes, and after it completes, the finally{} block executes. Regardless of the interruptions that can happen in b(), the finally block will be attempted.
Notice in Listing 1 that main() calls b() and then calls c(). Although b() couldn’t complete its processing (it was terminated), c() still executes. Although Listing 1 contains an oversimplification of exception handling, it demonstrates that the termination model doesn’t necessarily result in termination of the entire program.
The program in Listing 1 demonstrates some of the basics of the Java exception handling facility:
- Methods can throw exceptions, as is the case with a() in Listing 1.
- Methods can contain exception handlers, as is the case with b() in Listing 1.
- The finally block will always be attempted, even if the try or catch block throws an exception.
- When a method throws an exception, the flow of control is transferred to the nearest method that can handle the type of exception that was thrown.
- Exceptions have types, and user-defined types are always derived from built-in exception types.
How you use the basics of the Java exception handling facility reveals at least two important implications for the software architecture:
- The flow of control in the software architecture can be altered by the throw mechanism.
- The exception classes used introduce new types, and each type has its own semantics.
The transfer of control from the problem area to someplace that knows how to bring the system into a consistent state, and the semantics of the exception thrown, together allow us to start to reach for the goal of fault tolerance. The semantics of the exception thrown describe what the exceptional condition is and suggest what should be done. The transfer of control takes us to code that implements our exception strategy. The exception strategy is designed to make the software resilient to defects and system failures. In Java, the catch() mechanism either implements the exception strategy directly or creates objects and calls methods that implement the exception strategy:
catch(some_exception){ // Execute exception strategy }