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

クラスStackWalker



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

    walkメソッドは、現在のスレッドのStackFrameの連続ストリームを開き、与えられた関数を適用してStackFrameストリームをウォークします。 ストリームは、スタックが生成された実行ポイントを表す一番上のフレームから一番下のフレームまで、順番にスタック・フレーム要素を報告します。 walkメソッドが戻ると、StackFrameストリームが閉じます。 クローズ・ドストリームを再利用しようとすると、IllegalStateExceptionがスローされます。

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

    StackWalkerはスレッド・セーフです。 複数のスレッドは、1つの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である場合、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 option
        戻り値:
        指定されたオプションで構成された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の注:
        たとえば、宣言クラスがパッケージcom.fooにあるフレームを最初にスキップして最初の10個の呼び出しフレームを検索するには、次のようにします:
        
         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_FRAMESSHOW_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());
         
        getCallerClassメソッドが、スタックの一番下のフレームであるメソッドから呼び出されると、javaランチャによって起動されたstatic public void mainメソッド、またはJNIにアタッチされたスレッドから呼び出されたメソッドIllegalCallerExceptionがスローされます。
        戻り値:
        Classこのメソッドを呼び出す呼び出し側呼び出し元のオブジェクト。
        例外:
        UnsupportedOperationException - このStackWalkerOption.RETAIN_CLASS_REFERENCEで構成されていない場合。
        IllegalCallerException - 呼び出し元フレームがない場合、つまりこのgetCallerClassメソッドがスタック上の最後のフレームであるメソッドから呼び出された場合。