13 Printing Event Stack Trace

The example StackTraceSample.java prints information about an event's stack trace.

StackTraceSample uses the Event Streaming API (see Monitor Events with Flight Recorder Event Streaming API) to print stack trace information of WithStackTrace events. The sample recursively calls the method firstFunc six times. This method creates an event named WithStackTrace. Every time an WithStackTrace occurs, information about the event's stack trace is printed.

import java.util.List;
import java.util.function.Consumer;

import jdk.jfr.Event;
import jdk.jfr.EventType;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
import jdk.jfr.consumer.RecordedEvent;
import jdk.jfr.consumer.RecordedFrame;
import jdk.jfr.consumer.RecordedStackTrace;
import jdk.jfr.consumer.RecordingStream;

public class StackTraceSample {

    @Name("com.oracle.WithStackTrace")
    @Label("With Stack Trace")
    @StackTrace(true)
    static class WithStackTrace extends Event {
        String message;
    }

    public static void main(String... args) throws Exception {
        Consumer<RecordedEvent> myCon = x -> {
            EventType et = x.getEventType();
            System.out.println("Label: " + et.getLabel());
            System.out.println("Message: " + x.getValue("message"));
            RecordedStackTrace rst = x.getStackTrace();
            if (rst != null) {
                List<RecordedFrame> frames = rst.getFrames();
                System.out.println(
                    "Number of frames: " + frames.size());
                for (RecordedFrame rf : frames) {
                    System.out.println("Method, line number: "
                        + rf.getMethod().getName() + ", "
                        + rf.getLineNumber());
                }
            }
            System.out.println("");
        };

        try (RecordingStream rs = new RecordingStream()) {
            rs.onEvent("com.oracle.WithStackTrace", myCon);
            rs.startAsync();
            firstFunc(5);
            rs.awaitTermination();
        }
    }

    static void firstFunc(int n) {
        if (n > 0) {
            secondFunc(n - 1);
        }
        WithStackTrace event = new WithStackTrace();
        event.message = "n = " + n;
        event.commit();

    }

    static void secondFunc(int n) {
        firstFunc(n);
    }
}

The example StackTraceSample prints output similar to the following:

Label: With Stack Trace
Message: n = 0
Number of frames: 12
Method, line number: firstFunc, 97
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: main, 86

Label: With Stack Trace
Message: n = 1
Number of frames: 10
Method, line number: firstFunc, 97
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: main, 86

Label: With Stack Trace
Message: n = 2
Number of frames: 8
Method, line number: firstFunc, 97
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: main, 86

Label: With Stack Trace
Message: n = 3
Number of frames: 6
Method, line number: firstFunc, 97
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: main, 86

Label: With Stack Trace
Message: n = 4
Number of frames: 4
Method, line number: firstFunc, 97
Method, line number: secondFunc, 102
Method, line number: firstFunc, 93
Method, line number: main, 86

Label: With Stack Trace
Message: n = 5
Number of frames: 2
Method, line number: firstFunc, 97
Method, line number: main, 86

An event's stack trace, an instance of RecordedStackTrace, consists of a list of RecordedFrame instances. You can obtain the following information from a RecordedFrame with these methods:

  • getMethod(): Returns the method from which the event was run.
  • getLineNumber(): Returns the line number from which the event was run.
  • isJavaFrame(): Indicates whether the RecordedFrame is a Java frame.
  • getBytecodeIndex(): Returns the bytecode index from which the event was run.
  • getType(): Returs the frame type; possible values include Interpreted, JIT compiled, and Inlined.

Flight Recorder uses a default stack depth of 64 method calls, which is more than enough for this example. You can change this with the stackdepth command-line option:

-XX:FlightRecorderOptions:stackdepth=depth

Note that values greater than 64 could create significant overhead and reduce performance.