StackWalker API ถูกนำเข้ามาใน Java 9 ให้ snapshot ของ stack trace ของ current thread ได้ทุกเวลา และมีเมธอด walk over it ข้อดีของ StackWalker class เหนือ Thread::getStackTrace() คือสามารถ filter หรือ skip คลาสบางคลาสได้ และได้ instance ของ declaring class เอง ได้ either short หรือ full stack trace แทนที่จะ pull complete stack trace ทั้งหมด
ตัวอย่างโค้ด: ใช้ Stream.skip()
import java.lang.StackWalker.*;
import java.util.Optional;
import java.util.List;
import java.util.stream.Collectors;
import java.lang.StackWalker.StackFrame;
public class StackWalkerSkipTest {
public static void main(String args[]) {
new StackWalkerSkipTest().stackWalk();
}
private class StackWalker4 {
public void stackWalk4() {
List<StackFrame> framesAfterSkip = StackWalker.getInstance(
StackWalker.Option.RETAIN_CLASS_REFERENCE
).walk(s -> s.skip(2).collect(Collectors.toList()));
System.out.println("Frames after skip : \n" + framesAfterSkip.toString());
}
}
public void stackWalk() {
new StackWalker1().stackWalk1();
}
private class StackWalker1 {
public void stackWalk1() {
new StackWalker2().stackWalk2();
}
}
private class StackWalker2 {
public void stackWalk2() {
new StackWalker3().stackWalk3();
}
}
private class StackWalker3 {
public void stackWalk3() {
new StackWalker4().stackWalk4();
}
}
}
ผลลัพธ์
Frames after skip : [
StackWalkerSkipTest$StackWalker2.stackWalk2(StackWalkerSkipTest.java:29),
StackWalkerSkipTest$StackWalker1.stackWalk1(StackWalkerSkipTest.java:24),
StackWalkerSkipTest.stackWalk(StackWalkerSkipTest.java:19),
StackWalkerSkipTest.main(StackWalkerSkipTest.java:9)
]
คำอธิบาย
- Call stack: main → stackWalk → stackWalk1 → stackWalk2 → stackWalk3 → stackWalk4
skip(2) ข้าม 2 frames บนสุด (stackWalk4 และ stackWalk3)
- เหลือ frames ตั้งแต่ stackWalk2 ลงมา
StackWalker Skip/Drop Methods
| เมธอด |
คำอธิบาย |
| skip(long n) |
ข้าม n frames แรก (จากบนลงล่าง) |
| limit(long n) |
จำกัดจำนวน frames สูงสุด n frames |
| dropWhile(Predicate) |
ข้าม frames ตราบใดที่ predicate เป็น true |
| takeWhile(Predicate) |
รับ frames ตราบใดที่ predicate เป็น true |
ตัวอย่างเพิ่มเติม
// ข้าม frames จนกว่าจะเจอ class ที่ไม่ใช่ internal
StackWalker.getInstance().walk(s -> s
.dropWhile(f -> f.getClassName().startsWith("java."))
.dropWhile(f -> f.getClassName().startsWith("jdk."))
.collect(Collectors.toList())
);
// เอาแค่ 5 frames บนสุด
StackWalker.getInstance().walk(s -> s
.limit(5)
.collect(Collectors.toList())
);
// ข้าม 3 frames แล้วเอา 5 frames
StackWalker.getInstance().walk(s -> s
.skip(3)
.limit(5)
.collect(Collectors.toList())
);
StackFrame Methods
| เมธอด |
คืนค่า |
คำอธิบาย |
| getClassName() |
String |
ชื่อคลาสเต็ม |
| getMethodName() |
String |
ชื่อเมธอด |
| getLineNumber() |
int |
บรรทัดใน source (-1 ถ้า unknown, -2 ถ้า native) |
| getFileName() |
String |
ชื่อไฟล์ source |
| getDeclaringClass() |
Class<?> |
Class object (ต้อง RETAIN_CLASS_REFERENCE) |
| isNativeMethod() |
boolean |
เป็น native method หรือไม่ |