Java : StackWalker with Examples

StackWalker (Java SE 18 & JDK 18) API Examples.
You will find code examples on most StackWalker methods.


Summary

A stack walker.

Class diagram

public class Main {

    public static void main(String[] args) {
        func();
    }

    private static void func() {
        final var foo = new Foo();
        foo.aaa();
    }
}
public class Foo {
    public void aaa() {
        bbb();
    }

    private void bbb() {
        final var sw = StackWalker.getInstance();

        System.out.println("-- forEach --");
        sw.forEach(System.out::println);

        // Result
        // ↓
        //-- forEach --
        //Foo.bbb(Foo.java:12)
        //Foo.aaa(Foo.java:5)
        //Main.func(Main.java:11)
        //Main.main(Main.java:6)

        System.out.println("-- forEach --");
        sw.forEach(action -> {
            System.out.println(" -- action --");
            System.out.println("  file : " + action.getFileName());
            System.out.println("  line :" + action.getLineNumber());
            System.out.println("  class :" + action.getClassName());
            System.out.println("  method :" + action.getMethodName());
        });

        // Result
        // ↓
        //-- forEach --
        // -- action --
        //  file : Foo.java
        //  line :22
        //  class :Foo
        //  method :bbb
        // -- action --
        //  file : Foo.java
        //  line :5
        //  class :Foo
        //  method :aaa
        // -- action --
        //  file : Main.java
        //  line :11
        //  class :Main
        //  method :func
        // -- action --
        //  file : Main.java
        //  line :6
        //  class :Main
        //  method :main
    }
}

Methods

void forEach (Consumer<? super StackWalker.StackFrame> action)

Performs the given action on each element of StackFrame stream of the current thread, traversing from the top frame of the stack, which is the method calling this forEach method.

public class Main {

    public static void main(String[] args) {
        func1();
    }

    private static void func1() {
        func2();
    }

    private static void func2() {
        final var sw = StackWalker.getInstance();

        System.out.println("-- forEach --");
        sw.forEach(System.out::println);

        // Result
        // ↓
        //-- forEach --
        //Main.func2(Main.java:17)
        //Main.func1(Main.java:10)
        //Main.main(Main.java:6)
    }
}

Class<?> getCallerClass ()

Gets the Class object of the caller who invoked the method that invoked getCallerClass.

public class Main {

    public static void main(String[] args) {

        final var foo = new Foo();
        foo.func();

        // Result
        // ↓
        //Foo : getCallerClass = class Main
        //Bar : getCallerClass = class Foo
    }
}
public class Foo {

    public void func() {
        final var sw = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
        System.out.println("Foo : getCallerClass = " + sw.getCallerClass());

        final var bar = new Bar();
        bar.func();
    }
}
public class Bar {

    public void func() {
        final var sw = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
        System.out.println("Bar : getCallerClass = " + sw.getCallerClass());
    }
}
class A {
    void func() {
        final var sw = StackWalker.getInstance();
        try {
            final var ret = sw.getCallerClass();
        } catch (UnsupportedOperationException e) {
            System.out.println(e);
        }
    }
}

class B {
    void func() {
        new A().func();
    }
}

new B().func();

// Result
// ↓
//java.lang.UnsupportedOperationException:
//  This stack walker does not have RETAIN_CLASS_REFERENCE access

static StackWalker getInstance ()

Returns a StackWalker instance.

Please see forEach(Consumer<? super StackWalker.StackFrame> action).

static StackWalker getInstance (StackWalker.Option option)

Returns a StackWalker instance with the given option specifying the stack frame information it can access.

Please see getCallerClass().

static StackWalker getInstance (Set<StackWalker.Option> options)

Returns a StackWalker instance with the given options specifying the stack frame information it can access.

import java.lang.reflect.InvocationTargetException;

public class Main {

    public static void main(String[] args) throws NoSuchMethodException,
            InvocationTargetException, IllegalAccessException {

        final var foo = new Foo();

        final var method = Foo.class.getDeclaredMethod("func");
        method.invoke(foo);

        // Result
        // ↓
        //-- with options --
        //Foo.func(Foo.java:16)
        //java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
        //java.base/java.lang.reflect.Method.invoke(Method.java:577)
        //Main.main(Main.java:13)
        //getCallerClass : class Main
        //
        //-- no options --
        //Foo.func(Foo.java:24)
        //Main.main(Main.java:13)
    }
}
import java.util.Set;

public class Foo {

    public void func() {
        {
            final var options = Set.of(
                    StackWalker.Option.SHOW_REFLECT_FRAMES,
                    StackWalker.Option.RETAIN_CLASS_REFERENCE
            );

            System.out.println("-- with options --");
            final var sw = StackWalker.getInstance(options);
            sw.forEach(System.out::println);

            System.out.println("getCallerClass : " + sw.getCallerClass());
        }

        {
            System.out.println("-- no options --");
            final var sw = StackWalker.getInstance();
            sw.forEach(System.out::println);
        }
    }
}

static StackWalker getInstance (Set<StackWalker.Option> options, int estimateDepth)

Returns a StackWalker instance with the given options specifying the stack frame information it can access.

Please see also : getInstance(Set<StackWalker.Option> options)

public class Main {

    public static void main(String[] args) {

        new Foo().func1();

        // Result
        // ↓
        //-- forEach --
        //Foo.func2(Foo.java:18)
        //Foo.func1(Foo.java:8)
        //Main.main(Main.java:7)
        //getCallerClass : class Foo
    }
}
import java.util.Set;

public class Foo {

    public void func1() {
        func2();
    }

    private void func2() {
        final var options = Set.of(
                StackWalker.Option.RETAIN_CLASS_REFERENCE
        );

        System.out.println("-- forEach --");
        final var sw = StackWalker.getInstance(options, 5);
        sw.forEach(System.out::println);

        System.out.println("getCallerClass : " + sw.getCallerClass());
    }
}

<T> T walk (Function<? super Stream<StackWalker.StackFrame>,? extends T> function)

Applies the given function to the stream of StackFrames for the current thread, traversing from the top frame of the stack, which is the method calling this walk method.

public class Main {

    public static void main(String[] args) {

        aaa1();

        // Result
        // ↓
        //-- forEach --
        //Main.bbb2(Main.java:39)
        //Main.bbb1(Main.java:31)
        //Main.aaa2(Main.java:27)
        //Main.aaa1(Main.java:23)
        //Main.main(Main.java:7)
        //-- walk --
        //Main.aaa2(Main.java:27)
        //Main.aaa1(Main.java:23)
    }

    private static void aaa1() {
        aaa2();
    }

    private static void aaa2() {
        bbb1();
    }

    private static void bbb1() {
        bbb2();
    }

    private static void bbb2() {

        final var sw = StackWalker.getInstance();

        System.out.println("-- forEach --");
        sw.forEach(System.out::println);

        System.out.println("-- walk --");
        final var list = sw.walk(
                stream -> stream.filter(
                        stackFrame -> stackFrame.getMethodName().startsWith("aaa")
                ).toList()
        );

        list.forEach(System.out::println);
    }
}

Related posts

To top of page