Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

Java 9 StackWalker API로 특정 스택 프레임 건너뛰는 방법

StackWalker API란?

StackWalker APIJava 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<?>) 객체를 직접 참조할 수 있어, 리플렉션 없이도 클래스 정보를 빠르고 효율적으로 얻을 수 있습니다.