モジュール java.base
パッケージ java.lang

クラスStackWalker


  • public final class StackWalker
    extends Object
    Stack Walkerです。

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

    StackWalkerスタック・ウォーキング・オプションによって、返されるStackFrameオブジェクトの情報が決まります。 デフォルトでは、リフレクションAPIおよび実装クラスのスタック・フレームは非表示になり、StackFrameには使用可能なクラス名とメソッド名がありますが、Class referenceは使用できません。

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

    APIのノート:

    1. 実装クラスの既知のリストをフィルタ処理する最初の呼出し側を検索するには:

    
         StackWalker walker = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);
         Optional<Class<?>> callerClass = walker.walk(s ->
             s.map(StackFrame::getDeclaringClass)
              .filter(interestingClasses::contains)
              .findFirst());
     

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

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

    導入されたバージョン:
    9
    • メソッドの詳細

      • getInstance

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

        セキュリティ・マネージャが存在し、指定されたoptionOption.RETAIN_CLASS_REFERENCEの場合は、そのcheckPermissionメソッドをRuntimePermission("getStackWalkerWithClassReference")に対してコールします。

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

        public static StackWalker getInstance​(Set<StackWalker.Option> options)
        指定されたoptionsで、アクセス可能なスタック・フレーム情報を指定したStackWalkerインスタンスを返します。 指定されたoptionsが空の場合、このStackWalkerはすべての非表示フレームをスキップするように構成され、クラス参照は保持されません。

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

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

        public static StackWalker getInstance​(Set<StackWalker.Option> options,
                                              int estimateDepth)
        指定されたoptionsで、アクセス可能なスタック・フレーム情報を指定したStackWalkerインスタンスを返します。 指定されたoptionsが空の場合、このStackWalkerはすべての非表示フレームをスキップするように構成され、クラス参照は保持されません。

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

        estimateDepthは、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)
              .collect(Collectors.toList()));
         

        このメソッドは、Stream<StackFrame>を返し、呼出し側がストリームを直接操作できるようにするのではなく、Stream<StackFrame>を受け入れるFunctionを取ります。 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(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メソッドが呼び出された場合。