如何使用 Java 中的 StackWalker API 來列印不同的堆疊框架?


Java 9 定義了一個 StackWalker API ,它提供延遲和幀過濾。一個 StackWalker 物件允許我們遍歷和訪問堆疊,幷包含一個有用的方法:walk()。此方法為當前執行緒開啟一個 StackFrame 流 ,然後使用該 StackFrame 流應用該函式。我們需要獲取 StackWalker 物件,然後使用 StackWalker.getInstance() 方法。

在下面的示例中,我們可以列印不同的堆疊框架:all 堆疊框架、skip 一些堆疊框架,以及使用 StackWalker API 來limit 堆疊框架。

示例

import java.lang.StackWalker.StackFrame;
import java.util.*;
import java.util.stream.*;

public class StackWalkerTest {
   public static void main(String args[]) {
      new StackWalkerTest().walk();
   }
   private void walk() {
      new Walker1().walk();
   }
   private class Walker1 {
      public void walk() {
         new Walker2().walk();
      }
   }
   private class Walker2 {
      public void walk() {
         Method1();
      }
      void Method1() {
         Method2();
      }
      void Method2() {
         StackWalker stackWalker = StackWalker.getInstance(Set.of(StackWalker.Option.RETAIN_CLASS_REFERENCE, StackWalker.Option.SHOW_HIDDEN_FRAMES), 16);
         Stream<StackFrame> stackStream = StackWalker.getInstance().walk(f -> f);

         System.out.println("--- Walk all StackFrames ---");
         List<String> stacks = walkAllStackframes();
         System.out.println(stacks);

         System.out.println("--- Skip some StackFrames ---");
         List<String> stacksAfterSkip = walkSomeStackframes(3);
         System.out.println(stacksAfterSkip);

         System.out.println("--- Limit StackFrames ---");
         List<String> stacksByLimit = walkLimitStackframes(3);
         System.out.println(stacksByLimit);
      }
      private List<String> walkAllStackframes() {
         return StackWalker.getInstance().walk(s -> s.map(frame -> "\n" + frame.getClassName() + "/" + frame.getMethodName()).collect(Collectors.toList()));
      }
      private List<String> walkSomeStackframes(int numberOfFrames) {
         return StackWalker.getInstance().walk(s -> s.map(frame -> "\n" + frame.getClassName() + "/" + frame.getMethodName()).skip(numberOfFrames).collect(Collectors.toList()));
      }
      private List<String> walkLimitStackframes(int numberOfFrames) {
         return StackWalker.getInstance().walk(s -> s.map(frame -> "\n" + frame.getClassName() + "/" + frame.getMethodName()).limit(numberOfFrames).collect(Collectors.toList())); 
      }
   }
}

輸出

--- Walk all StackFrames ---
[
StackWalkerTest$Walker2/walkAllStackframes,
StackWalkerTest$Walker2/Method2,
StackWalkerTest$Walker2/Method1,
StackWalkerTest$Walker2/walk,
StackWalkerTest$Walker1/walk,
StackWalkerTest/walk,
StackWalkerTest/main
]
--- Skip some StackFrames ---
[
StackWalkerTest$Walker2/walk,
StackWalkerTest$Walker1/walk,
StackWalkerTest/walk,
StackWalkerTest/main
]
--- Limit StackFrames ---
[
StackWalkerTest$Walker2/walkLimitStackframes,
StackWalkerTest$Walker2/Method2,
StackWalkerTest$Walker2/Method1
]

更新時間:2020-03-11

224 次訪問

啟動您的 職業生涯

完成課程獲得認證

開始
廣告
© . All rights reserved.