Stackwalker has less frames than stacktrace has elements

Viewed 280

I was experimenting a bit with the Stackwalking API of Java 9 and noticed that the frames collected are less than the ones given by the actual stack trace. I was wondering whether it is possible to get an identical number of frames and elements?

Have a look at the following test:

@Test
public void test() {
    NaughtyBusiness nb = new NaughtyBusiness();
    try {
        //This method throws an exception
        nb.callMeForGoodTime(NaughtyBusiness.AlcoholTolerance.LOW);
    } catch (Exception e) {
        StackTraceElement[] stackTrace = e.getStackTrace();

        StackWalker stackWalker = StackWalker.getInstance(StackWalker.Option.SHOW_HIDDEN_FRAMES);
        List<StackWalker.StackFrame> frames = 
                            stackWalker.walk(stackFrameStream -> stackFrameStream.collect(toList()));
       
        System.out.println(frames);
    }
}

Now if I debug the code I see the following:

enter image description here

The first obvious difference, is the number of StacktraceElements vs StackFrames (26 vs 23). More surprisingly though, the missing frames (marked in red) are the ones that are actually interesting, i.e. from my custom code, whereas the green part that is shared among both is just boilerplate.

The question therefore is, how am I able to get the "missing" frames with the StackWalking API? I've tried the 3 options SHOW_HIDDEN_FRAMES, RETAIN_CLASS_REFERENCE and SHOW_REFLECT_FRAMES but none worked.

1 Answers

The StackWalker.walk method builds stack frames from the point where it was called. In this case, you called it from the test() method, so it builds a sequence of stack frames starting with that method.

StackWalker doesn’t know about your caught exception at all. The exception was thrown from a different place, namely the NaughtyBusiness.playStupidGamesWinStupidPrizes method, which is why its stack frames are different.

To get StackWalker frames which are identical to the exception's stack frames, you need to call StackWalker.walk from the same method which threw the exception.

Related