Zoeken…


Invoering

Vóór Java 9 was de toegang tot de sun.reflect.Reflection beperkt tot een interne klasse sun.reflect.Reflection . Specifiek de methode sun.reflect.Reflection::getCallerClass . Sommige bibliotheken vertrouwen op deze methode die is verouderd.

Een alternatieve standaard API wordt nu in JDK 9 via de java.lang.StackWalker klasse en is ontworpen efficiënt doordat lui toegang tot de stapel frames. Sommige toepassingen kunnen deze API gebruiken om de uitvoeringsstapel te doorlopen en op klassen te filteren.

Druk alle stapelframes van de huidige thread af

Het volgende drukt alle stapelframes van de huidige thread af:

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 }

Output:

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

Huidige bellersklasse afdrukken

Het volgende drukt de huidige bellersklasse af. Merk op dat in dit geval de StackWalker moet worden gemaakt met de optie RETAIN_CLASS_REFERENCE , zodat Class instanties worden behouden in de StackFrame objecten. Anders zou een uitzondering optreden.

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

Output:

class test.FooHelper

Reflectie en andere verborgen frames weergeven

Met een paar andere opties kunnen stacktraces implementatie- en / of reflectiekaders bevatten. Dit kan handig zijn voor het opsporen van fouten. We kunnen bijvoorbeeld de optie SHOW_REFLECT_FRAMES toevoegen aan de StackWalker instantie bij het maken, zodat de frames voor de reflectiemethoden ook worden afgedrukt:

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

Output:

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

Merk op dat regelnummers voor sommige reflectiemethoden mogelijk niet beschikbaar zijn, dus StackFrame.getLineNumber() kan negatieve waarden retourneren.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow