Java 9 มอบ standard API ผ่านคลาส java.lang.StackWalker คลาสนี้ออกแบบให้มีประสิทธิภาพโดยอนุญาต lazy access ไปยัง stack frames มี options อื่นๆ อนุญาตให้ stack trace รวม implementation และ/หรือ reflection frames ซึ่งมีประโยชน์สำหรับ debugging ตัวอย่าง เพิ่ม option SHOW_REFLECT_FRAMES ให้ StackWalker instance ตอนสร้าง เพื่อพิมพ์ frames สำหรับ reflective methods ด้วย
ตัวอย่างโค้ด
import java.lang.StackWalker.Option;
import java.lang.StackWalker.StackFrame;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;
public class ReflectionFrameTest {
public static void main(String args[]) throws NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method test1Method = Test1.class.getDeclaredMethod("test1", (Class>[]) null);
test1Method.invoke(null, (Object[]) null);
}
}
class Test1 {
protected static void test1() {
Test2.test2();
}
}
class Test2 {
protected static void test2() {
// show reflection methods
List<StackFrame> stack = StackWalker.getInstance(Option.SHOW_REFLECT_FRAMES)
.walk(s -> s.collect(Collectors.toList()));
for (StackFrame frame : stack) {
System.out.println(frame.getClassName() + " " +
frame.getLineNumber() + " " +
frame.getMethodName());
}
}
}
ผลลัพธ์
Test2 22 test2
Test1 16 test1
jdk.internal.reflect.NativeMethodAccessorImpl -2 invoke0
jdk.internal.reflect.NativeMethodAccessorImpl 62 invoke
jdk.internal.reflect.DelegatingMethodAccessorImpl 43 invoke
java.lang.reflect.Method 564 invoke
ReflectionFrameTest 11 main
คำอธิบาย
- Test2.test2() - เริ่มต้น stack walk
- Test1.test1() - เรียก Test2.test2()
- NativeMethodAccessorImpl.invoke0 - native reflection entry point (line -2 = native)
- NativeMethodAccessorImpl.invoke - Java wrapper
- DelegatingMethodAccessorImpl.invoke - delegation layer
- Method.invoke - public reflection API
- ReflectionFrameTest.main - จุดเริ่มต้น
StackWalker Options
| Option | คำอธิบาย |
|---|---|
| SHOW_REFLECT_FRAMES | แสดง reflection frames (Method.invoke, etc.) |
| SHOW_HIDDEN_FRAMES | แสดง hidden frames (lambda, method handles) |
| RETAIN_CLASS_REFERENCE | เก็บ Class reference ไว้ใน StackFrame |
การใช้งานร่วมกัน
// หลาย options พร้อมกัน
StackWalker walker = StackWalker.getInstance(
Option.SHOW_REFLECT_FRAMES,
Option.RETAIN_CLASS_REFERENCE
);
// ใช้ walk กับ function
walker.walk(frames -> frames
.filter(f -> f.getClassName().startsWith("com.myapp"))
.collect(Collectors.toList())
);
// หรือ forEach
walker.forEach(frame -> System.out.println(frame));
ข้อดีของ StackWalker vs Thread.getStackTrace()
- Lazy evaluation - ไม่สร้าง stack trace ทั้งหมดทันที
- Filtering - กรอง frames ได้ก่อน collect
- Class reference - ได้ Class object จริง (ด้วย RETAIN_CLASS_REFERENCE)
- Performance - ดีกว่าสำหรับการใช้งานบ่อย