13 イベント・スタック・トレースの出力

StackTraceSampleの例では、イベントのスタック・トレースが出力されます。ここでは、メソッドfirstFuncが6回呼び出されます。

StackTraceSampleはイベント・ストリームAPI (「Flight Recorderイベント・ストリームAPIを使用したイベントの監視」を参照)を使用して、WithStackTraceイベントのスタック・トレース情報を出力します。

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);
    }
}

StackTraceSampleの例では、次のような出力が表示されます:

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

イベントのスタック・トレース(RecordedStackTraceのインスタンス)は、RecordedFrameインスタンスのリストで構成されています。下に示すメソッドを使用して、RecordedFrameから次の情報を取得できます:

  • getMethod(): イベントの実行元のメソッドを返します。
  • getLineNumber(): イベントの実行元の行番号を返します。この例では、行番号29が文event.commit();です。
  • isJavaFrame(): RecordedFrameがJavaフレームかどうかを示します。
  • getBytecodeIndex(): イベントの実行元のバイトコード・インデックスを返します。
  • getType(): フレーム・タイプを返します。使用される値は、InterpretedJIT compiledおよびInlinedです。

Flight Recorderは、デフォルトのスタック深度が64メソッド呼出しで、この例では十二分です。これは、stackdepthコマンド行オプションで次のようにして変更できます:

-XX:FlightRecorderOptions:stackdepth=depth

64よりも大きい値を指定すると、大量のオーバーヘッドが発生し、パフォーマンスが低下する可能性があることに注意してください。