Sök…


Introduktion

Före Java 9 var åtkomsten till trådstackramarna begränsad till en intern klass sun.reflect.Reflection . Specifikt metoden sun.reflect.Reflection::getCallerClass . Vissa bibliotek förlitar sig på den här metoden som avskrivs.

En alternativ standard-API tillhandahålls nu i JDK 9 via java.lang.StackWalker klassen, och är utformad för att vara effektiv genom att tillåta lat tillträde till stackramar. Vissa applikationer kan använda detta API för att korsa exekveringsstacken och filtrera på klasser.

Skriv ut alla stapelramar för den aktuella tråden

Följande skriver ut alla stapelramar i den aktuella tråden:

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 }

Produktion:

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

Skriv ut aktuell anropsklass

Följande skriver ut den aktuella anropsklassen. Notera att i detta fall StackWalker måste skapas med alternativet RETAIN_CLASS_REFERENCE , så att Class instanser kvar i StackFrame objekt. Annars skulle ett undantag inträffa.

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

Produktion:

class test.FooHelper

Visar reflektion och andra dolda ramar

Ett par andra alternativ tillåter stapelspår att inkludera implementerings- och / eller reflektionsramar. Detta kan vara användbart för felsökning. Vi kan till exempel lägga till alternativet SHOW_REFLECT_FRAMES i StackWalker instansen vid skapandet, så att ramarna för de reflekterande metoderna också skrivs ut:

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

Produktion:

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

Observera att radnummer för vissa reflektionsmetoder kanske inte är tillgängliga så StackFrame.getLineNumber() kan returnera negativa värden.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow