October 30, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Chained Exceptions in Java

  • July 23, 2002
  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

Throw the exception

The code in meth03 then throws the IndexOutOfBoundsException object, and that terminates the catch block.

Find an appropriate handler

At this point, the runtime system starts searching for a catch block capable of accepting an incoming object reference of type IndexOutOfBoundsException.  This could be a catch block designed to accept a parameter of type IndexOutOfBoundsException, or any superclass of IndexOutOfBoundsException.

Such a catch block is found in the method named meth02, which is the method that originally called meth03.  In other words, the method named meth02 is the next method encountered when moving up through the call stack.

The code for the method named meth02 is shown in Listing 3.
 

  void meth02() throws NewEx02{

    try{
      meth03();
    }//end try

    catch(RuntimeException e){
      System.out.println(
              "In meth02 catch block");
      System.out.println(
         "Msg is:\n" + e.getMessage());
      System.out.println(
         "Cause is:\n" + e.getCause());
      System.out.println();
      throw new NewEx02(
                  "Msg from meth02",e);
    }//end catch
  }//end meth02

Listing 3

This method also has a try block followed by a catch block.  The try block contains a single statement, which is a call to the method named meth03(This is how control reached meth03 in the first place.)  As we saw in Listing 2, meth03 throws an IndexOutOfBoundsException, which is a subclass of RuntimeException.

Not a checked exception

Because it is a subclass of RuntimeException, it is not a checked exception.  Therefore, it is not necessary for meth03 to declare that it throws the exception.

However, even though the exception is not declared in the signature for meth03, the author of meth02 can still elect to monitor for and catch the exception if it gets thrown.  (The purposeful handling of unchecked exceptions is optional.)

As the author of meth02, I did elect to monitor for and handle all exceptions of type RuntimeException.  Hence, the parameter type specified in the catch block in meth02 is RuntimeException.  The reference to any RuntimeException that may be caught is known locally by the name e within the catch block.

Behavior of the catch block in meth02

The code in the catch block in Listing 3 begins by getting and displaying the message and the cause encapsulated in the incoming object of type RuntimeException.  The output is similar to that shown in Figure 3.   (I manually inserted some newline characters to force the material to fit in this narrow format.)
 

In meth02 catch block
Msg is:
Msg from metho03
Cause is:
java.lang.ArithmeticException:
/ by zero

Figure 3

The output

The ability to get and display the message encapsulated in an incoming exception object has been a part of Java for a very long time.  However, the ability to get and display the cause, by invoking the getCause method on the exception object, (which is highlighted in boldface in Listing 3), is new to JDK 1.4.  (The result of invoking the getCause method in Listing 3 is highlighted in boldface in the output shown in Figure 3.)

Format of cause information

Note that in this display format, the cause shows not only the name of the class, (java.lang.ArithmeticException), from which the cause object was instantiated, but also displays the message, (/ by zero), that was encapsulated in the cause object when it was instantiated by the runtime system.

Throw another exception containing a cause

After getting and displaying the message and the cause, the code in the catch block in Listing 3 throws a new object of the class NewEx02, passing the RuntimeException object's reference as the cause parameter to the constructor.

(In this case, the cause was encapsulated in the object when the object was instantiated rather than encapsulating it later by invoking the initCause method on a reference to the object.)


This is a checked exception

Note that because NewEx02 extends Exception, making it a checked exception, the method named meth02 in Listing 3 must declare that it throws NewEx02.

Catch the exception

The exception thrown by the method named meth02 is caught by the method named meth01, which is the next method up the call stack.  The method named meth01 is shown in Listing 4.
 

  void meth01() throws NewEx01{
    try{
      meth02();
    }//end try block

    catch(NewEx02 e){
      System.out.println(
              "In meth01 catch block");
      System.out.println(
         "Msg is:\n" + e.getMessage());
      System.out.println(
         "Cause is:\n" + e.getCause());
      System.out.println();//blank line
      throw new NewEx01(
                  "Msg from meth01",e);
    }//end catch
  }//end meth01

Listing 4

Catch block is very similar

The code in the catch block in meth01 is very similar to that shown earlier for meth02.  In particular, it begins by getting and displaying the message and the cause encapsulated in the incoming object of type NewEx02, know locally by the name e.

The output

The output produced by this code is similar to that shown in Figure 4.  In this case, the cause is displayed as the combination of the IndexOutOfBoundsException object and the message object encapsulated in the NewEx02 object when it was instantiated and thrown.
 

In meth01 catch block
Msg is:
Msg from meth02
Cause is:
java.lang.IndexOutOfBoundsException: 
 Msg from metho03

Figure 4

Throw one more exception containing a cause

After displaying the message and the cause, the code in the catch block in Listing 4 instantiates and throws a new object of the class NewEx01.  This object encapsulates a reference to the NewEx02 object received as an incoming parameter to the catch block as the cause object.

Again, because NewEx01 is a checked exception, the method named meth01 must declare that it can be thrown.

Catch the exception again

This exception is caught by the next method up the call stack, which is the main method of the Excep20 class.  The beginning of the main method is shown in Listing 5.
 

  public static void main(
                        String[] args){
    try{
      new Class01().meth01();
    }//end try

    catch(NewEx01 e){
      System.out.println(
                "In main catch block");
      System.out.println(
         "Msg is:\n" + e.getMessage());
      System.out.println(
         "Cause is:\n" + e.getCause());

Listing 5

Get and display the message and the cause

As before, the code in Listing 5 gets and displays the message and the cause encapsulated in the incoming object to the catch block.  By now, there shouldn't be any surprises in the output produced by the code in Listing 5.  The output is similar to that shown in Figure 5.
 

In main catch block
Msg is:
Msg from meth01
Cause is:
NewEx02: Msg from meth02

Figure 5

Now for something new

Listing 6 shows the remainder of the catch block in the main method.
 

      System.out.println(
                   "Print StackTrace");
      e.printStackTrace();
    }//end catch

Listing 6

Invoke the printStackTrace method

The code in Listing 6 invokes the upgraded printStackTrace method on the incoming parameter received by the catch block.  This parameter is a reference to the object of type NewEx01, thrown by the method named meth01.

The printStackTrace method has been a part of Java for many years.  However, it was upgraded in JDK 1.4 to support the cause facility.  In particular, this method now produces a complete history of the chain of exceptions.

The output

The output produced by the invocation of the printStackTrace method in Listing 6 is similar to that shown in Figure 6.  (Again, I had to manually insert some line breaks to cause the material to fit in this narrow publication format.)
 

NewEx01: Msg from meth01
 at Class01.meth01(Excep20.java:124)
 at Excep20.main(Excep20.java:61)
Caused by: NewEx02: Msg from meth02
 at Class01.meth02(Excep20.java:141)
 at Class01.meth01(Excep20.java:115)
 ... 1 more
Caused by: 
 java.lang.IndexOutOfBoundsException: 
  Msg from metho03
 at Class01.meth03(Excep20.java:151)
 at Class01.meth02(Excep20.java:132)
 ... 2 more
Caused by: 
 java.lang.ArithmeticException: 
  / by zero
 at Class01.meth03(Excep20.java:149)
 ... 3 more

Figure 6

The chain of exceptions

Starting at the bottom of Figure 6 and reading up, you can see that the chain begins with the innermost exception that was thrown.  That exception was an ArithmeticException thrown by the runtime system when the code in meth03 attempted to perform an integer divide by zero operation on source code line number 149.

The chain ends with the exception of type NewEx01, thrown by the method named meth01, and caught by the main method.

The initCause method

Recall that the ArithmeticException was wrapped as the cause in an IndexOutOfBoundsException object, which is a legacy class that predates the release of JDK 1.4.  The new initCause method was used to wrap the ArithmeticException object as the cause in the IndexOutOfBoundsException object.

Wrapping with a constructor

That IndexOutOfBoundsException object was wrapped as the cause in an exception object of type NewEx02.  The NewEx02 class is a new class that provides constructors matching the new constructors of the Throwable class.  The IndexOutOfBoundsException object was wrapped in the NewEx02 object when it was instantiated.

The NewEx02 object was in turn wrapped as the cause in an exception object of type NewEx01, when that object was instantiated.  The cause was available to the catch block in the main method.

The complete causal history

The complete causal history is displayed in the stack trace of Figure 6.  Prior to the release of JDK 1.4, there was no standard way to create and display a chain of exceptions as illustrated by Figure 6.

Programmatic access to stack trace information

In addition to the upgraded printStackTrace method illustrated in Figure 6, a new getStackTrace method was added in release 1.4, which provides programmatic access to the same stack trace information displayed by the printStackTrace method.  This makes it possible for you to write code that can make decisions on the basis of information contained in the stack trace.  I didn't demonstrate that capability in this lesson, but I hope to demonstrate it in a future lesson that deals heavily with matters involving the stack trace.





Page 3 of 4



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel