Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Java

Cách in các stack frame khác nhau dùng StackWalker API trong Java

Java 9 StackWalker API cung cấp laziness và frame filtering. Object StackWalker cho phép duyệt stack, phương thức chính: walk(). Mở Stream<StackFrame> cho thread hiện tại, apply function. Lấy instance qua StackWalker.getInstance().

Ví dụ: In all / skip / limit stack frames

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()));
        }
    }
}

Kết quả

--- 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 ]

Giải thích

Phương thứcStream operationKết quả
walkAllStackframes.collect(toList())Toàn bộ stack (bottom → top)
walkSomeStackframes(3).skip(3).collect(toList())Bỏ 3 frame đầu (top), lấy phần còn lại
walkLimitStackframes(3).limit(3).collect(toList())Chỉ lấy 3 frame đầu (top)

Ưu điểm StackWalker

  • Lazy: Chỉ materialize frame khi stream consume.
  • Filterable: Dùng Stream API (filter, map, skip, limit).
  • Class reference: Với RETAIN_CLASS_REFERENCE, lấy được Class<?>.
  • Hidden frames: Có option hiển thị frame ẩn (reflection, lambda, method handle).
  • Performance: Tránh allocate array toàn bộ stack trace như getStackTrace().

StackWalker API là công cụ mạnh cho profiling, logging, diagnostic, error reporting trong Java 9+.