Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

วิธีพิมพ์ stack frames ต่างๆ ด้วย StackWalker API ใน Java

Java 9 กำหนด StackWalker API ให้ laziness และ frame filtering ออบเจ็กต์ของ StackWalker ให้ traverse และเข้าถึง stacks ได้ มีเมธอดมีประโยชน์: walk() เมธอดนี้เปิด StackFrame stream สำหรับเธรดปัจจุบัน แล้ว apply function กับ StackFrame stream ต้องได้ StackWalker object ก่อนด้วย StackWalker.getInstance()

ตัวอย่าง: พิมพ์ 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()));
        }
    }
}

ผลลัพธ์

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

สรุปการใช้งาน

การดำเนินการเมธอด Streamคำอธิบาย
Walk allcollect()รวบรวมทุก frame
Skip framesskip(n)ข้าม n frames แรก (มักเป็น frames ของ StackWalker เอง)
Limit frameslimit(n)เอาแค่ n frames แรก (frames ล่าสุด)
Filter by classfilter(f -> ...)กรองเฉพาะ frame ของคลาสที่ต้องการ

StackWalker ให้ API แบบ functional programming ทำให้จัดการ stack trace ง่ายและมีประสิทธิภาพ