August 21, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Processing Stack Trace Data in Java

  • September 17, 2002
  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

What does the output represent?

The first line of output represents the type of one Throwable object, and the message encapsulated in that object.

The second line of output represents one stack frame that existed at the point in time that the Throwable object was created and thrown.  If the stack contained more than one frame, other lines similar to the second line would be produced, one for each stack frame.

Wrap up the display method

Listing 20 shown the remaining code in the display method, including the ends of the inner and outer enumeration loops.
 

      }//end inner while loop
      System.out.println();//blank line
    }//end outer while loop
  }//end display

Listing 20

The full output

Figure 3 shows the full output produced by the display method in this program.
 

NewEx01: Thrown from meth02
  Class01.meth02(StackTr01.java:92)
  Class01.meth01(StackTr01.java:60)
  StackTr01.main(StackTr01.java:52)
NewEx02: Thrown from meth03
  Class01.meth03(StackTr01.java:102)
  Class01.meth02(StackTr01.java:85)
  Class01.meth01(StackTr01.java:60)
  StackTr01.main(StackTr01.java:52)
NewEx03: Thrown from meth04
  Class01.meth04(StackTr01.java:112)
  Class01.meth03(StackTr01.java:100)
  Class01.meth02(StackTr01.java:85)
  Class01.meth01(StackTr01.java:60)
  StackTr01.main(StackTr01.java:52)

Figure 3

Throwable objects in the chain of exceptions

From this output, we can see that three separate Throwable objects were thrown in the chain of exceptions.  The first object that was thrown and the state of the stack at the time it was created and thrown are identified by the boldface text at the bottom of Figure 3.

As shown by the top boldface line of text, the first object that was thrown was of type NewEx03.  The message reads: "Thrown from meth04".

Five frames on the stack

There were five frames on the stack at the time the object was thrown.  According to Sun:

"All stack frames except for the one at the top of the stack represent a method invocation. The frame at the top of the stack represents the execution point at which the stack trace was generated. Typically, this is the point at which the throwable corresponding to the stack trace was created."
The frame at the bottom of the stack represents the main method of the StackTr01 class.

The frame at the top of the stack represents the method named meth04 of the class named Class01.  This is the method that threw the first exception.  The line number of 112 "represents the execution point at which the stack trace was generated."

When was the Throwable object created?

The stack trace data indicates that the object was created at line 112 in the source code for the program.  Lines 112 and 113 in the source code read as shown in Figure 4.
 

112 throw new NewEx03(
113             "Thrown from meth04");

Figure 4
(Although the statement that created the Throwable object is spread across two lines, it begins on line 112.)
Method invocations

As indicated in the earlier quotation from Sun, the remaining line numbers in the boldface text represent method invocations in the methods and classes indicated.

For example, the statements corresponding to the line numbers in the last four lines in Figure 3 are shown in Figure 5.  As you can see, each of these statements is a method invocation.
 

100  meth04();//in meth03
 85  meth03();//in meth02
 60  meth02();//in meth01
 52  new Class01().meth01();//in main

Figure 5

Compare with printed stack trace data

At this point, I recommend that you compare Figure 3 with Figure 1.  Figure 1 shows the output from the printStackTrace method for this program.  Figure 3 shows my programmatic formatting of stack trace data for the same program.  Except for the fact that some of the data is missing in Figure 1, you should be able to match up each of the data elements in Figure 3 with the corresponding data elements in Figure 1.

Programmatic handling of stack trace data

Now you know how to get stack trace information and encapsulate it in an object suitable for processing under program control.  You know how to serialize that data so that it can be written in a disk file or transmitted across a network.  You know how to read the serialized byte stream and reconstruct the original object containing the stack trace data.

Equally important, you also know how to interpret the stack trace data that is available in this fashion.  Obviously, you can't write code to process the stack trace data, and make decisions on the basis of that data, unless you know how to interpret it.

Run the Program

If you haven't already done so, I encourage you to copy the code from Listing 21 into your text editor, compile it, and execute it.  Experiment with it, making changes, and observing the results of your changes.

Remember, however, that you must be running Java version 1.4 or later to compile and execute this program.

Complete Program Listing

A complete listing of the program discussed in this lesson is shown in Listing 21.
 
/*File StackTr01.java  
Copyright 2002, R. G. Baldwin
Illustrates programmatic handling of
stack trace data for the case where
the stack trace includes causal 
information.

Tested using JDK 1.4.0 under Win2000

The output produced by the program is
similar to the following:

Print StackTrace
NewEx01: Thrown from meth02
 at Class01.meth02(StackTr01.java:92)
 at Class01.meth01(StackTr01.java:60)
 at StackTr01.main(StackTr01.java:52)
Caused by: NewEx02: Thrown from meth03
 at Class01.meth03(StackTr01.java:102)
 at Class01.meth02(StackTr01.java:85)
 ... 2 more
Caused by: NewEx03: Thrown from meth04
 at Class01.meth04(StackTr01.java:112)
 at Class01.meth03(StackTr01.java:100)
 ... 3 more
NewEx01: Thrown from meth02
  Class01.meth02(StackTr01.java:92)
  Class01.meth01(StackTr01.java:60)
  StackTr01.main(StackTr01.java:52)
NewEx02: Thrown from meth03
  Class01.meth03(StackTr01.java:102)
  Class01.meth02(StackTr01.java:85)
  Class01.meth01(StackTr01.java:60)
  StackTr01.main(StackTr01.java:52)
NewEx03: Thrown from meth04
  Class01.meth04(StackTr01.java:112)
  Class01.meth03(StackTr01.java:100)
  Class01.meth02(StackTr01.java:85)
  Class01.meth01(StackTr01.java:60)
  StackTr01.main(StackTr01.java:52)
**************************************/

import java.io.*;
import java.util.*;
import java.util.logging.*;

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

class Class01{
  void meth01(){
    try{
      meth02();//call meth02
    }catch(Exception e){
      System.out.println(
                   "Print StackTrace");
      e.printStackTrace();
      //Encapsulate stack information
      // in a Vector
      Vector vecOuter = encapsulate(e);
      
      //Write the Vector to disk as a
      // serialized object for demo
      writeSer(vecOuter,"junk");
      //Read the serialized data and
      // reconstruct the Vector object
      Vector vecIn = 
               (Vector)readSer("junk");
      //Display the stack trace data
      // in the Vector object
      display(vecIn);
    }//end catch    
  }//end meth01
  //---------------------------------//
  
  void meth02() throws NewEx01{
    try{
      meth03();
    }catch(Exception e){
      //Construct and throw a new
      // exception object with the
      // exception caught by this
      // method encapsulated as the
      // cause
      throw new NewEx01(
               "Thrown from meth02",e);
    }//end catch
  }//end meth02
  //---------------------------------//
  
  void meth03() throws NewEx02{
    try{
      meth04();
    }catch(Exception e){      
      throw new NewEx02(
               "Thrown from meth03",e);
    }//end catch
  }//end meth03
  //---------------------------------//
  
  void meth04() throws NewEx03{
    //Construct and unconditionally
    // throw a new exception object
    // with no encapsulated cause
    throw new NewEx03(
                 "Thrown from meth04");
  }//end meth04
  //---------------------------------//
  
  //Method to encapsulate stack 
  // information in a Vector 
  // containing refs to other Vector 
  // objects
  Vector encapsulate(Throwable e){
    Vector vecOuter = new Vector();
    //Treat the incoming Throwable
    // as a cause
    Throwable cause = e;
    //Drill down to the point where
    // there is no cause encapsulated
    // in the cause
    while(cause != null){
      //Get the StackTraceElement for
      // this cause
      StackTraceElement[] trace 
               = cause.getStackTrace();
      //Create a Vector to contain
      // data from this
      // StackTraceElement
      Vector vec = new Vector();
      //Include high-level information
      // about this cause in the vector
      vec.add("Cause" 
                   + cause.toString());
      //Loop, get, and save four pieces
      // of data for each item in the
      // StackTraceElememt.  Each piece
      // of data is saved as a String
      // with an identifier prepended.
      for(int i=0;i<trace.length;i++){
        vec.add("Class" + trace[i].

                       getClassName());
        vec.add("Method" + trace[i].
                      getMethodName());
        vec.add("File" + trace[i].
                        getFileName());
        vec.add("Line" + trace[i].
                      getLineNumber());
      }//end for loop
      //Add this Vector object to the
      // outer enclosing vector
      vecOuter.add(vec);
      //Continue drilling down. Get the
      // cause encapsulated in this
      // cause and start over.  Exit
      // the loop when getCause returns
      // null
      cause = cause.getCause();      
    }//end while loop
    return vecOuter;
  }//end encapsulate
  //---------------------------------//
  
  //Method to serialize the Vector and
  // write it to a disk file.
  void writeSer(Object obj, 
                          String name){
    try{//to serialize the Vector obj
      ObjectOutputStream  outStream  =
               new  ObjectOutputStream(
                  new FileOutputStream(
                                name));
      outStream.writeObject(obj);
      outStream.flush();
      outStream.close();
    }catch(Exception excp){
      System.out.println(excp);
    }//end catch
  }//end writeSer
  //---------------------------------//
  
  //Method to read the serialized data,
  // reconstruct, and return the Vector
  // object
  Object readSer(String name){
    try{
      ObjectInputStream inStream = 
                 new ObjectInputStream(
                   new FileInputStream(
                                name));
      return inStream.readObject();
       
    }catch(Exception excp){
      System.out.println(excp);
    }//end catch
    //required to satisfy compiler
    return null;
  }//end readSer
  //---------------------------------//
  
  //Method to display the stack trace
  // data encapsulated in the Vector
  // in a specific format
  void display(Vector vecOuter){
    Enumeration enumOuter = 
                   vecOuter.elements();
    while(enumOuter.hasMoreElements()){
      Vector vecInner = (Vector)
               enumOuter.nextElement();
      Enumeration enumInner = 
                   vecInner.elements();
      while(enumInner.
                    hasMoreElements()){
        String str = (String)
               enumInner.nextElement();
        if(str.startsWith("Cause")){
          System.out.print(
                 str.substring("Cause".
                            length()));
        }else if(str.startsWith(
                             "Class")){
          System.out.println();
          System.out.print("  " 
               + str.substring("Class".
                            length()));
        }else if(str.startsWith(
                            "Method")){
          System.out.print("." 
              + str.substring("Method".
                            length()));
        }else if(str.startsWith(
                              "File")){
          System.out.print("(" 
                + str.substring("File".
                            length()));
        }else if(str.startsWith(
                              "Line")){
          System.out.print(":" 
                + str.substring("Line".
                      length()) + ")");
        }//end else
      }//end while loop
      System.out.println();
    }//end while loop
  }//end display
  //---------------------------------//
}//end Class01
//===================================//

//Note:  For brevity, I included only
// the required constructors in these
// new exception classes.
//This is a new exception class
class NewEx01 extends Exception{
  public NewEx01(String message,
                  Throwable throwable){
    super(message, throwable);
  }
}//end NewEx01
//===================================//

//This is a new exception class
class NewEx02 extends Exception{
  public NewEx02(String message,
                 Throwable throwable){
    super(message, throwable);
  }
}//end NewEx02
//===================================//

//This is a new exception class
class NewEx03 extends Exception{
  public NewEx03(String message){
    super(message);
  }
}//end NewEx03

Listing 21


Copyright 2002, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard G. Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects, and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Programming Tutorials, which has gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

baldwin@DickBaldwin.com

-end-
 



Page 3 of 3



Comment and Contribute

 


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

 

 


Sitemap | Contact Us

Rocket Fuel