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.
Source Code (CallStack.java) Source Code (MethodCaller.java)