クラスStackWalker

java.lang.Object
java.lang.StackWalker

public final class StackWalker extends Object
スタック・ウォーカ。

walkメソッドは、現在のスレッドに対してStackFrameの順次ストリームを開き、指定された関数を適用してStackFrameストリームを調査します。 ストリームは、スタックが生成された実行ポイントを表す最上位のフレームから最下位のフレームまで、スタック・フレーム要素を順番にレポートします。 walkメソッドが戻ると、StackFrameストリームは閉じられます。 クローズしたストリームを再利用しようとすると、IllegalStateExceptionがスローされます。

スタック・ウォーカ・オプションは、StackWalkerによって取得されるスタック・フレーム情報を構成します。 デフォルトでは、クラス名とメソッド情報は収集されますが、Class referenceは収集されません。 メソッド情報は、DROP_METHOD_INFOオプションを使用して削除できます。 Classオブジェクトは、RETAIN_CLASS_REFERENCEオプションを使用してアクセスするために保持できます。 リフレクションAPIおよび実装クラスのスタック・フレームは、デフォルトではhiddenです。

StackWalkerはスレッド・セーフです。 複数のスレッドが単一のStackWalkerオブジェクトを共有して、独自のスタックを横断できます。 権限チェックは、リクエストするオプションに従って、StackWalkerの作成時に実行されます。 スタック・ウォーキング時にこれ以上の権限チェックは行われません。

APIのノート:

1. 最初の呼び出し元が既知の実装クラスのリストをフィルタリングして検索するには:

    StackWalker walker = StackWalker.getInstance(Set.of(Option.DROP_METHOD_INFO, Option.RETAIN_CLASS_REFERENCE));
    Optional<Class<?>> callerClass = walker.walk(s ->
            s.map(StackFrame::getDeclaringClass)
             .filter(Predicate.not(implClasses::contains))
             .findFirst());

2. 現在のスレッドの上位10スタック・フレームのスナップショットを作成するには、

    List<StackFrame> stack = StackWalker.getInstance().walk(s -> s.limit(10).toList());
特に明記しないかぎり、このStackWalkerクラスのコンストラクタまたはメソッドにnull引数を渡すと、NullPointerExceptionがスローされます。

導入されたバージョン:
9
  • ネストされたクラスのサマリー

    ネストされたクラス
    修飾子と型
    クラス
    説明
    static enum 
    StackWalkerで取得した「スタック・フレーム」情報を構成するオプション。
    static interface 
    StackFrameオブジェクトは、StackWalkerによって返されるメソッド呼び出しを表します。
  • メソッドのサマリー

    修飾子と型
    メソッド
    説明
    void
    現在のスレッドのStackFrameストリームの各要素に対して、このforEachメソッドをコールするメソッドであるスタックのトップ・フレームから移動して、指定されたアクションを実行します。
    getCallerClassを呼び出したメソッドを呼び出した呼び出し元のClassオブジェクトを取得します。
    StackWalkerインスタンスを返します。
    アクセス可能なスタック・フレーム情報を指定する、指定されたオプションを使用してStackWalkerインスタンスを返します。
    アクセス可能なスタック・フレーム情報を指定する、指定されたoptionsを持つStackWalkerインスタンスを返します。
    getInstance(Set<StackWalker.Option> options, int estimateDepth)
    アクセス可能なスタック・フレーム情報を指定する、指定されたoptionsを持つStackWalkerインスタンスを返します。
    <T> T
    walk(Function<? super Stream<StackWalker.StackFrame>,? extends T> function)
    指定された関数を現在のスレッドのStackFrameのストリームに適用し、スタックの上部フレーム(このwalkメソッドをコールするメソッド)から移動します。

    クラスjava.lang.Objectで宣言されたメソッド

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • メソッドの詳細

    • getInstance

      public static StackWalker getInstance()
      StackWalkerインスタンスを返します。

      このStackWalkerは、すべての「隠しフレーム」をスキップするように構成されており、「クラス参照」は保持されません。

      戻り値:
      すべての「隠しフレーム」をスキップするように構成されたStackWalker「クラス参照」は保持されません。
    • getInstance

      public static StackWalker getInstance(StackWalker.Option option)
      アクセス可能なスタック・フレーム情報を指定する、指定されたオプションを使用してStackWalkerインスタンスを返します。

      セキュリティ・マネージャが存在し、指定されたoptionOption.RETAIN_CLASS_REFERENCEである場合、RuntimePermission("getStackWalkerWithClassReference")checkPermissionメソッドを呼び出します。

      パラメータ:
      option - stack walking option
      戻り値:
      指定されたオプションで構成されたStackWalker
      例外:
      SecurityException - セキュリティ・マネージャが存在し、そのcheckPermissionメソッドがアクセスを拒否した場合。
    • getInstance

      public static StackWalker getInstance(Set<StackWalker.Option> options)
      アクセス可能なスタック・フレーム情報を指定する、指定されたoptionsを持つStackWalkerインスタンスを返します。

      指定されたoptionsが空の場合、このStackWalkerはすべての「隠しフレーム」をスキップするように構成され、「クラス参照」は保持されません。

      セキュリティ・マネージャが存在し、指定されたoptionsOption.RETAIN_CLASS_REFERENCEが含まれている場合、RuntimePermission("getStackWalkerWithClassReference")checkPermissionメソッドが呼び出されます。

      パラメータ:
      options - stack walking options
      戻り値:
      指定されたオプションで構成されたStackWalker
      例外:
      SecurityException - セキュリティ・マネージャが存在し、そのcheckPermissionメソッドがアクセスを拒否した場合。
    • getInstance

      public static StackWalker getInstance(Set<StackWalker.Option> options, int estimateDepth)
      アクセス可能なスタック・フレーム情報を指定する、指定されたoptionsを持つStackWalkerインスタンスを返します。

      指定されたoptionsが空の場合、このStackWalkerはすべての「隠しフレーム」をスキップするように構成され、「クラス参照」は保持されません。

      セキュリティ・マネージャが存在し、指定されたoptionsOption.RETAIN_CLASS_REFERENCEが含まれている場合、RuntimePermission("getStackWalkerWithClassReference")checkPermissionメソッドが呼び出されます。

      estimateDepthは、StackWalkerがバッファ・サイズのヒントとして使用できる、このStackWalkerが移動するスタック・フレームの見積り数を指定します。

      パラメータ:
      options - stack walking options
      estimateDepth - トラバースされるスタック・フレームの推定数。
      戻り値:
      指定されたオプションで構成されたStackWalker
      例外:
      IllegalArgumentException - estimateDepth <= 0の場合
      SecurityException - セキュリティ・マネージャが存在し、そのcheckPermissionメソッドがアクセスを拒否した場合。
    • walk

      public <T> T walk(Function<? super Stream<StackWalker.StackFrame>,? extends T> function)
      指定された関数を現在のスレッドのStackFrameのストリームに適用し、スタックの上部フレーム(このwalkメソッドをコールするメソッド)から移動します。

      このメソッドが返されると、StackFrameストリームが閉じられます。 閉じたStream<StackFrame>オブジェクトが再利用されると、IllegalStateExceptionがスローされます。

      APIのノート:
      たとえば、最初の10個の呼び出しフレームを検索するには、最初に宣言クラスがパッケージcom.foo内にあるフレームをスキップします:
      List<StackFrame> frames = StackWalker.getInstance().walk(s ->
              s.dropWhile(f -> f.getClassName().startsWith("com.foo."))
               .limit(10)
               .toList());
      

      このメソッドは、Stream<StackFrame>を返し、呼出し側がストリームを直接操作できるようにするのではなく、Functionを使用してStream<StackFrame>を受け入れます。 Java仮想マシンは、たとえば最適化解除によって、スレッドの制御スタックを自由に再編成できます。 このメソッドは、Functionパラメータを取得することで、スレッドの制御スタックの安定したビューを介してスタック・フレームにアクセスできます。

      パラレル実行は事実上無効になり、ストリーム・パイプラインの実行は現在のスレッドでのみ行われます。

      実装上のノート:
      実装では、スタック・ウォーキングに固有のフレームを固定してスタックを安定させ、スタック・ウォーキングがアンカーされたフレームの上で実行されるようにします。 ストリーム・オブジェクトがクローズされるか、再利用されると、IllegalStateExceptionがスローされます。
      型パラメータ:
      T - 「スタック・フレーム」のストリームに関数を適用した結果の型。
      パラメータ:
      function - 「スタック・フレーム」のストリームを取得し、結果を返すファンクション。
      戻り値:
      「スタック・フレーム」のストリームに関数を適用した結果。
    • forEach

      public void forEach(Consumer<? super StackWalker.StackFrame> action)
      現在のスレッドのStackFrameストリームの各要素に対して、このforEachメソッドをコールするメソッドであるスタックのトップ・フレームから移動して、指定されたアクションを実行します。

      このメソッドは、

      walk(s -> { s.forEach(action); return null; });

      パラメータ:
      action - 現在のスレッドのスタックの各StackFrameに対して実行されるアクション
    • getCallerClass

      public Class<?> getCallerClass()
      getCallerClassを呼び出したメソッドを呼び出した呼び出し元のClassオブジェクトを取得します。

      このメソッドは、このStackWalkerが構成されているSHOW_REFLECT_FRAMESおよびSHOW_HIDDEN_FRAMESオプションに関係なく、「反射枠」MethodHandleおよび「隠しフレーム」をフィルタ処理します。

      このメソッドは、呼出し側フレームが存在する場合にコールする必要があります。 スタックの最下位フレームからコールされると、IllegalCallerExceptionがスローされます。

      このStackWalkerRETAIN_CLASS_REFERENCEオプションで構成されていない場合、このメソッドはUnsupportedOperationExceptionをスローします。

      APIのノート:
      たとえば、Util::getResourceBundleは、コール元のかわりにリソース・バンドルをロードします。 getCallerClassを呼び出して、Util::getResourceBundleというメソッドを持つクラスを識別します。 次に、そのクラスのクラス・ローダーを取得し、クラス・ローダーを使用してリソース・バンドルをロードします。 この例の呼び出し元クラスはMyToolです。
      class Util {
          private final StackWalker walker =
              StackWalker.getInstance(Set.of(Option.DROP_METHOD_INFO, Option.RETAIN_CLASS_REFERENCE));
          public ResourceBundle getResourceBundle(String bundleName) {
              Class<?> caller = walker.getCallerClass();
              return ResourceBundle.getBundle(bundleName, Locale.getDefault(), caller.getClassLoader());
          }
      }
      
      class MyTool {
          private final Util util = new Util();
          private void init() {
              ResourceBundle rb = util.getResourceBundle("mybundle");
          }
      }
      
      walkメソッドを使用して呼び出し元クラスを検索する同等の方法は、次のとおりです。(リフレクション・フレーム、MethodHandleおよび非表示フレームのフィルタリング):
          Optional<Class<?>> caller = walker.walk(s ->
              s.map(StackFrame::getDeclaringClass)
               .skip(2)
               .findFirst());
      
      javaランチャによって起動されたstatic public void mainメソッドや、JNIアタッチされたスレッドから起動されたメソッドなど、スタックの最下位フレームであるメソッドからgetCallerClassメソッドがコールされると、IllegalCallerExceptionがスローされます。
      戻り値:
      このメソッドを呼び出す呼出し側のコール元のClassオブジェクト。
      例外:
      UnsupportedOperationException - このStackWalkerOption.RETAIN_CLASS_REFERENCEで構成されていない場合。
      IllegalCallerException - 呼出し側フレームがない場合、つまり、スタックの最後のフレームであるメソッドからこのgetCallerClassメソッドが呼び出された場合。