Reputation: 232
How does Java generate a thread's stack trace?
Example:
Consider functionA
calls functionB
calls functionC
calls functionD
. If at any point in functionD
getStackTraceElementArray
is used it would give the array of functionCalls:
functionC->functionB->functionA
How does Java fill the StackTraceElement
array at runtime? Assuming it fills the calling function when it reaches inside the called function, how does the JVM get the reference of the calling method inside the called method?
Upvotes: 2
Views: 365
Reputation: 98630
In the simplest case the stack trace is obtained from... the stack!
Each thread has a frame pointer (FP) register that points to the base address of a current stack frame. When a Java method is called, it first creates a new stack frame, i.e. it pushes a bunch of information onto the stack:
Then it updates FP to point to the newly created frame.
This way, you see, the frame pointers make a linked list: if I read a value pointed by FP, I get the base address of the previous frame.
Now notice that for each frame a method ID is always at the same offset from FP. So the stack walking is as easy as a while
loop (written in pseudo-code):
address fp = currentThread.getFP();
while (fp != null) {
methodID m = (methodID) read_stack_at(fp + METHOD_OFFSET);
print_method(m);
fp = (address) read_stack_at(fp);
}
That's how it works inside JVM for interpreted methods. Compiled methods are a bit more complicated. They do not usually save a method reference on the stack. Instead there is a structure that maps addresses of compiled code to the metadata that contains compiled method info. But the idea of stack walking is still the same.
Upvotes: 4