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

วิธีข้ามคลาสบางคลาสใน StackFrame ด้วย Java 9

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 หรือไม่