Java : StackWalker (スタックトレース) - API使用例
StackWalker (Java SE 18 & JDK 18) の使用例まとめです。
だいたいのメソッドを網羅済みです。
API仕様のおともにどうぞ。
概要
StackWalker は、現在のスレッドのスタックトレース(StackFrame) を取得するためのクラスです。
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);
// 結果
// ↓
//-- 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());
});
// 結果
// ↓
//-- 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
}
}
メソッド
void forEach (Consumer<? super StackWalker.StackFrame> action)
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);
// 結果
// ↓
//-- forEach --
//Main.func2(Main.java:17)
//Main.func1(Main.java:10)
//Main.main(Main.java:6)
}
}
Class<?> getCallerClass ()
public class Main {
public static void main(String[] args) {
final var foo = new Foo();
foo.func();
// 結果
// ↓
//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();
// 結果
// ↓
//java.lang.UnsupportedOperationException:
// This stack walker does not have RETAIN_CLASS_REFERENCE access
static StackWalker getInstance ()
このメソッドの使用例は、forEach(Consumer<? super StackWalker.StackFrame> action) にまとめて記載しました。
そちらのAPI使用例をご参照ください。
static StackWalker getInstance (StackWalker.Option option)
このメソッドの使用例は、getCallerClass() にまとめて記載しました。
そちらのAPI使用例をご参照ください。
static StackWalker getInstance (Set<StackWalker.Option> options)
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);
// 結果
// ↓
//-- 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)
関連:getInstance(Set<StackWalker.Option> options)
public class Main {
public static void main(String[] args) {
new Foo().func1();
// 結果
// ↓
//-- 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)
public class Main {
public static void main(String[] args) {
aaa1();
// 結果
// ↓
//-- 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);
}
}