Java
 Computer >> コンピューター >  >> プログラミング >> Java

Java 9でスレッドのスタックトレースを取得する方法:Thread.getStackTrace()とStackWalkerクラスの使い方

Java 9では、現在実行中のスレッドのスタックへアクセスするための標準APIとして、StackWalkerクラスが新たに追加されました。それ以前のJavaバージョンでは、Throwable::getStackTraceThread::getStackTraceSecurityManager::getClassContextといったメソッドを使用してスレッドスタックを取得していました。

Thread.getStackTrace()メソッドは、対象スレッドのスタックダンプを表すStackTraceElement[](スタックトレース要素の配列)を返します。配列の最初の要素はスタックの最上部、すなわち一連のメソッド呼び出しの中で最後に実行されたメソッドを表し、配列の最後の要素はスタックの最下部、すなわち最初に呼び出されたメソッドを表します。

構文

public StackTraceElement[] getStackTrace()

コード例

import java.lang.StackWalker.Option;

public class GetStackTraceTest {
    public static void main(String args[]) {
        GetStackTraceTest.testPrintCurrnentStackTrace();
        GetStackTraceTest.testShowReflectFrames();
    }
    // Threadを使ってスタックトレースを取得
    public static void testPrintCurrnentStackTrace() {
        StackTraceElement[] stack = Thread.currentThread().getStackTrace();
        for(StackTraceElement element : stack) {
            System.out.println(element);
        }
    }
    // SHOW_REFLECT_FRAMESオプションを使用した例
    public static void print(StackWalker stackWalker) {
        stackWalker.forEach(stackFrame -> System.out.printf("%6d| %s -> %s %n",
stackFrame.getLineNumber(), stackFrame.getClassName(), stackFrame.getMethodName()));
    }

    public static void testShowReflectFrames() {
        final StackWalker stackWalker = StackWalker.getInstance(Option.SHOW_REFLECT_FRAMES);
        print(stackWalker);
    }
}

実行結果

java.base/java.lang.Thread.getStackTrace(Thread.java:1654)
GetStackTraceTest.testPrintCurrnentStackTrace(GetStackTraceTest.java:10)
GetStackTraceTest.main(GetStackTraceTest.java:5)
   17| GetStackTraceTest -> print
   25| GetStackTraceTest -> testShowReflectFrames
   6| GetStackTraceTest -> main

このように、従来のThread.getStackTrace()ではStackTraceElementの配列としてスタック情報を取得できます。一方、Java 9で導入されたStackWalkerクラスは、ラムダ式やストリームAPIと組み合わせてスタックフレームを効率的に走査できるのが特徴です。上記の例ではOption.SHOW_REFLECT_FRAMESを指定することで、通常は非表示になるリフレクション関連のフレームも含めて出力しています。パフォーマンスを考慮したスタック解析を行いたい場合は、StackWalkerの利用が推奨されます。

  1. Javaでif文を使ってIllegalArgumentExceptionを事前に回避する方法

    Javaでは、IllegalArgumentException(不正な引数例外)は、メソッドに渡された引数が不正な値である場合にスローされます。しかし、多くの場合、開発者はそのメソッドが受け付ける正当な引数の範囲をあらかじめ把握しています。そこで、if文を使って引数を実行前に検証(バリデーション)することで、例外の発生自体を防ぐことができます。 if文による引数の事前チェック if文を使えば、メソッドに渡す引数の値を制限できます。例えば、あるメソッドが特定の範囲内の値のみを受け入れる場合、メソッドを呼び出す前にif文で引数の範囲を確認すればよいのです。これにより、範囲外の値が渡されることを未然

  2. Javaでフォルダ内のディレクトリ(フォルダ)のみを取得する方法

    Javaで特定のフォルダに含まれるファイルではなく、ディレクトリ(サブフォルダ)だけを取得したいケースはよくあります。本記事では、代表的な2つの方法——FileFilterインターフェースを使う方法と、NIOのFiles.walk()を使う方法——をサンプルコード付きで解説します。listFiles()メソッドとFileFilterの基本FileクラスのlistFiles()メソッドは、そのFileオブジェクトが表すパスに含まれるすべてのファイルおよびディレクトリの抽象パス名を、配列として返します。ここで活躍するのがFileFilterインターフェースです。FileFilterはパス名をフィル