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 all | collect() | รวบรวมทุก frame |
| Skip frames | skip(n) | ข้าม n frames แรก (มักเป็น frames ของ StackWalker เอง) |
| Limit frames | limit(n) | เอาแค่ n frames แรก (frames ล่าสุด) |
| Filter by class | filter(f -> ...) | กรองเฉพาะ frame ของคลาสที่ต้องการ |
StackWalker ให้ API แบบ functional programming ทำให้จัดการ stack trace ง่ายและมีประสิทธิภาพ