Java 9에서는 현재 실행 중인 스레드의 스택에 접근할 수 있는 표준 API를 제공하는 StackWalker 클래스가 새롭게 도입되었습니다. 그 이전 버전의 Java에서는 Throwable::getStackTrace, Thread::getStackTrace, SecurityManager::getClassContext 등에서 제공하는 메서드를 통해 스레드 스택을 얻어야 했습니다.
Thread.getStackTrace() 메서드는 해당 스레드의 스택 덤프 정보를 담은 StackTraceElement[] 배열을 반환합니다. 배열의 첫 번째 요소는 스택의 최상단, 즉 시퀀스상 가장 마지막에 호출된 메서드를 의미하며, 배열의 마지막 요소는 스택의 최하단, 즉 가장 처음 호출된 메서드를 나타냅니다.
문법(Syntax)
public StackTraceElement[] getStackTrace()
예제 코드
import java.lang.StackWalker.Option;
public class GetStackTraceTest {
public static void main(String args[]) {
GetStackTraceTest.testPrintCurrnentStackTrace();
GetStackTraceTest.testShowReflectFrames();
}
// Thread를 사용하여 스택 트레이스 가져오기
public static void testPrintCurrnentStackTrace() {
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
for(StackTraceElement element : stack) {
System.out.println(element);
}
}
// SHOW_REFLECT_FRAMES 옵션 적용
public static void print(StackWalker stackWalker) {
stackWalker.forEach(stackFrame -> System.out.printf("%6d| %s -> %s %n",
stackFrame.getLineNumber(), stackFrame.getClassName(), stackFrame.getMethodName()));
}
public static void testShowReflectFrames() {
final StackWalker stackWalker = StackWalker.getInstance(Option.SHOW_REFLECT_FRAMES);
print(stackWalker);
}
}실행 결과
java.base/java.lang.Thread.getStackTrace(Thread.java:1654) GetStackTraceTest.testPrintCurrnentStackTrace(GetStackTraceTest.java:10) GetStackTraceTest.main(GetStackTraceTest.java:5) 17| GetStackTraceTest -> print 25| GetStackTraceTest -> testShowReflectFrames 6| GetStackTraceTest -> main
결과 해석 및 참고 사항
첫 번째 방식인 Thread.currentThread().getStackTrace()는 호출된 위치부터 스택의 하단까지 전체 호출 흐름을 문자열 형태로 간편하게 출력해 줍니다. 디버깅 시 현재 코드가 어떤 경로로 호출되었는지 빠르게 파악할 때 유용합니다.
반면 두 번째 방식인 StackWalker는 라인 번호, 클래스 이름, 메서드 이름을 개별적으로 다룰 수 있어 더 세밀한 제어가 가능합니다. 특히 Option.SHOW_REFLECT_FRAMES 옵션을 지정하면 기본적으로 숨겨지는 리플렉션(reflection) 관련 프레임까지 포함하여 스택 프레임을 확인할 수 있습니다. 성능이 중요한 환경에서는 필요한 만큼만 프레임을 탐색할 수 있는 StackWalker 사용이 권장됩니다.