StackWalker API란?
StackWalker API는 Java 9에서 새롭게 도입된 기능으로, 현재 스레드의 스택 트레이스(stack trace) 스냅샷을 원하는 시점에 캡처하고 이를 순차적으로 탐색할 수 있는 메서드를 제공합니다.
기존의 Thread::getStackTrace() 방식 대신 StackWalker 클래스를 사용하면 다음과 같은 장점이 있습니다.
- 특정 클래스를 필터링하거나 건너뛰기(skip)할 수 있습니다.
- 선언 클래스(declaring class) 자체의 인스턴스를 직접 얻을 수 있습니다.
- 전체 스택 트레이스를 통째로 가져오는 대신, 필요한 만큼의 짧은 스택 트레이스 또는 전체 스택 트레이스를 선택적으로 조회할 수 있습니다.
Stream.skip()으로 스택 프레임 건너뛰기
아래 예제에서는 java.util.stream.Stream.skip() 메서드를 사용해 지정한 개수만큼의 스택 프레임을 건너뛰는 방법을 살펴봅니다.
예제 코드
import java.lang.StackWalker.*;
import java.util.Optional;
import java.util.List;
import java.util.stream.Collectors;
import java.lang.StackWalker.StackFrame;
public class StackWalkerSkipTest {
public static void main(String args[]) {
new StackWalkerSkipTest().stackWalk();
}
private class StackWalker4 {
public void stackWalk4() {
List<StackFrame> framesAfterSkip = StackWalker.getInstance(
StackWalker.Option.RETAIN_CLASS_REFERENCE).walk((s) ->
s.skip(2).collect(Collectors.toList()));
System.out.println("Frames after skip : \n" + framesAfterSkip.toString());
}
}
public void stackWalk() {
new StackWalker1().stackWalk1();
}
private class StackWalker1 {
public void stackWalk1() {
new StackWalker2().stackWalk2();
}
}
private class StackWalker2 {
public void stackWalk2() {
new StackWalker3().stackWalk3();
}
}
private class StackWalker3 {
public void stackWalk3() {
new StackWalker4().stackWalk4();
}
}
}
실행 결과
Frames after skip : [StackWalkerSkipTest$StackWalker2.stackWalk2(StackWalkerSkipTest.java:29), StackWalkerSkipTest$StackWalker1.stackWalk1(StackWalkerSkipTest.java:24), StackWalkerSkipTest.stackWalk(StackWalkerSkipTest.java:19), StackWalkerSkipTest.main(StackWalkerSkipTest.java:9)]
결과 분석
실행 결과를 보면 skip(2) 호출로 인해 호출 스택의 가장 안쪽 두 프레임인 StackWalker4.stackWalk4()와 StackWalker3.stackWalk3()가 제외되고, 그보다 바깥쪽에 있는 프레임부터 순서대로 출력된 것을 확인할 수 있습니다.
또한 StackWalker.Option.RETAIN_CLASS_REFERENCE 옵션을 지정하면 각 스택 프레임에서 선언 클래스(Class<?>) 객체를 직접 참조할 수 있어, 리플렉션 없이도 클래스 정보를 빠르고 효율적으로 얻을 수 있습니다.