Suche…


Einführung

Vor Java 9 war der Zugriff auf die sun.reflect.Reflection auf eine interne Klasse sun.reflect.Reflection . Speziell die Methode sun.reflect.Reflection::getCallerClass . Einige Bibliotheken verlassen sich auf diese Methode, die veraltet ist.

Ein alternativer Standard - API wird nun in JDK 9 über die vorgesehen java.lang.StackWalker Klasse und wird , indem man lazy Zugang zu dem Stapelrahmen sein , effizient gestaltet. Einige Anwendungen können diese API verwenden, um den Ausführungsstapel zu durchsuchen und nach Klassen zu filtern.

Drucken Sie alle Stack-Frames des aktuellen Threads

Folgendes druckt alle Stack-Frames des aktuellen Threads:

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 }

Ausgabe:

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

Aktuelle Anruferklasse drucken

Im Folgenden wird die aktuelle Anruferklasse gedruckt. Beachten Sie, dass in diesem Fall die StackWalker mit der Option erstellt werden muss RETAIN_CLASS_REFERENCE , so dass die Class in den zurückgehalten werden StackFrame Objekte. Andernfalls würde eine Ausnahme auftreten.

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());
    }
}

Ausgabe:

class test.FooHelper

Reflektion und andere verborgene Frames anzeigen

Bei einigen anderen Optionen können Stack-Spuren Implementierungs- und / oder Reflektionsframes enthalten. Dies kann für Debugging-Zwecke hilfreich sein. Zum Beispiel können wir die Add SHOW_REFLECT_FRAMES Option zum StackWalker Beispiel bei der Erstellung, so dass der Rahmen für die reflektierenden Methoden als auch gedruckt werden:

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());
        }
    }
}

Ausgabe:

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

Beachten Sie, dass Zeilennummern für einige Reflektionsmethoden möglicherweise nicht verfügbar sind, sodass StackFrame.getLineNumber() negative Werte zurückgeben kann.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow