수색…


소개

Java 9 이전에는 스레드 스택 프레임에 대한 액세스가 내부 클래스 sun.reflect.Reflection 으로 제한되었습니다. 특히 sun.reflect.Reflection::getCallerClass 메소드. 일부 라이브러리는이 메소드 대신에 사용되지 않습니다.

또 다른 표준 API는 이제 통해 JDK (9)에서 제공 java.lang.StackWalker 클래스 및 스택 프레임에 게으른 접근을 허용함으로써 효율적으로 설계되어 있습니다. 일부 응용 프로그램은이 API를 사용하여 클래스의 실행 스택과 필터를 트래버스 할 수 있습니다.

현재 스레드의 모든 스택 프레임 인쇄

다음은 현재 스레드의 모든 스택 프레임을 인쇄합니다.

1  package test;
2  
3  import java.lang.StackWalker.StackFrame;
4  import java.lang.reflect.InvocationTargetException;
5  import java.lang.reflect.Method;
6  import java.util.List;
7  import java.util.stream.Collectors;
8  
9  public class StackWalkerExample {
10 
11    public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
12        Method fooMethod = FooHelper.class.getDeclaredMethod("foo", (Class<?>[])null);
13        fooMethod.invoke(null, (Object[]) null);
14    }
15 }
16
17 class FooHelper {
18    protected static void foo() {
19        BarHelper.bar();
20    }
21 }
22 
23 class BarHelper {
24    protected static void bar() {
25        List<StackFrame> stack = StackWalker.getInstance()
26                .walk((s) -> s.collect(Collectors.toList()));
27        for(StackFrame frame : stack) {
28            System.out.println(frame.getClassName() + " " + frame.getLineNumber() + " " + frame.getMethodName());
29        }
30    }
31 }

산출:

test.BarHelper 26 bar
test.FooHelper 19 foo
test.StackWalkerExample 13 main

현재 호출자 클래스 인쇄

다음은 현재 호출자 클래스를 인쇄합니다. 이 경우, StackWalkerRETAIN_CLASS_REFERENCE 옵션으로 생성되어야하므로 Class 인스턴스는 StackFrame 객체에 유지됩니다. 그렇지 않으면 예외가 발생합니다.

public class StackWalkerExample {

    public static void main(String[] args) {
        FooHelper.foo();
    }

}

class FooHelper {
    protected static void foo() {
        BarHelper.bar();
    }
}

class BarHelper {
    protected static void bar() {
        System.out.println(StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE).getCallerClass());
    }
}

산출:

class test.FooHelper

반사 및 기타 숨겨진 프레임 표시

몇 가지 다른 옵션은 스택 트레이스가 구현 및 / 또는 반사 프레임을 포함 할 수 있도록합니다. 디버깅 목적으로 유용 할 수 있습니다. 예를 들어, 생성시 StackWalker 인스턴스에 SHOW_REFLECT_FRAMES 옵션을 추가하여 반사 방식의 프레임도 인쇄 할 수 있습니다.

package test;

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 StackWalkerExample {

    public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Method fooMethod = FooHelper.class.getDeclaredMethod("foo", (Class<?>[])null);
        fooMethod.invoke(null, (Object[]) null);
    }
}

class FooHelper {
    protected static void foo() {
        BarHelper.bar();
    }
}

class BarHelper {
    protected static void bar() {
        // 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());
        }
    }
}

산출:

test.BarHelper 27 bar
test.FooHelper 20 foo
jdk.internal.reflect.NativeMethodAccessorImpl -2 invoke0
jdk.internal.reflect.NativeMethodAccessorImpl 62 invoke
jdk.internal.reflect.DelegatingMethodAccessorImpl 43 invoke
java.lang.reflect.Method 563 invoke
test.StackWalkerExample 14 main

일부 반사 방법의 행 번호는 사용할 수 없으므로 StackFrame.getLineNumber() 가 음수 값을 반환 할 수 있습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow