Call Stack Introspection

Scenario:
We have multiple files each containing numerous methods. For a given input, the methods makes calls to various methods in the class and methods of other classes. We would like to track all the calls made to other methods before the call reaches a particular method.

Solution[1]:
To solve our original problem, we could have a 'print out' line in each method but this becomes a problem when we might have thousands of classes each with numerous methods. However, the Reflection solution (presented below) can easily give us access to the class name, methods, and other properties. As a result, the solution with StackTraceElement is a better choice.

 

In order to track the calls made as per the description above, we can use the call stack that is associated with each thread being executed as well as Java Reflection. We illustrate the introspection of the call stack with MethodCaller and CallStack classes.
 

The MethodCaller class starts by making a call to methodA, which calls methodB and so on. When we reach methodC we are interested in learning what calls were made to get to methodC. We therefore call the print method of CallStack to give us that information.

 

Below is a code fragment from the print method of CallStack:

 

for (int i=1;i<ste.length;i++){
    System.out.println("Class: "+ste[i].getClassName());
    System.out.println("Method: "+ste[i].getMethodName());
    System.out.println("Line Number: "+ste[i].getLineNumber()+"\n");
}
 

The CallStack class first retrieves a reference to the call stack via Throwable’s getStackTrace method. The stack is saved as an array of StackTraceElement. The for loop then iterates through each element starting with 1 because the 0th element is the print method call. As result, we start from 1 to see where the call originated from. In each iteration of the for loop, we print out the name of the class, the method name, as well as the line number from which the call originated. From this information, we can trace the calls made to the methods to arrive at methodC.

 

Call Stack:

Class: MethodCaller

Method: methodC

Line Number: 22

 

Class: MethodCaller

Method: methodA

Line Number: 12

 

Class: MethodCaller

Method: methodB

Line Number: 17

 

Class: MethodCaller

Method: methodA

Line Number: 10

 

Class: MethodCaller

Method: main

Line Number: 5


Conclusion:
To solve our original problem, we could have put 'print out' line in each method but this becomes a problem when we might have thousands of classes each with numerous classes. Furthermore, the solution presented can easily give us access to the class name, methods, and other properties. As a result, the solution with StackTraceElement is a better choice.

 


[1] Java Reflection in Action was used as reference to develop the example

 

Source Code (CallStack.java)
Source Code (MethodCaller.java)



Home
Previous Example
Next Example
Source Code
References
Questions?