Java Language
Stack-Walking API
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.