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

วิธีแสดง Reflection Frames ของ StackFrame ใน Java 9

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 - ดีกว่าสำหรับการใช้งานบ่อย