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

Java 9 StackWalker API로 스택 프레임 필터링하는 방법

StackWalker API는 프로그램 실행 중에 스택 트레이스(stack trace) 정보를 스트림 형태로 제공합니다. 이 API는 가상 머신(VM)이 전체 스택의 스냅샷을 캡처하도록 요구하며, 필터링 작업을 위해 스택 프레임 요소들의 배열을 반환합니다. walk() 메서드를 사용하면 스택 프레임을 건너뛰거나(skip) 제거하고(drop) 개수를 제한(limit)할 수 있습니다. 또한 filter() 메서드를 활용해 클래스 기준으로 특정 조건에 맞는 첫 번째 스택 프레임만 가져오거나, 일치하는 모든 프레임을 한꺼번에 조회할 수도 있습니다.

StackWalker API의 주요 특징

  • 프로그램 실행 시점의 스택 트레이스 정보를 지연 평가(lazy evaluation) 방식의 스트림으로 제공합니다.
  • 불필요한 스택 프레임 생성 비용을 줄여 성능 면에서 유리합니다.
  • RETAIN_CLASS_REFERENCE 옵션을 사용하면 각 프레임의 선언 클래스(Class 객체)에 접근할 수 있습니다.

아래 예제는 StackWalker API를 사용하여 클래스 기준으로 스택 프레임을 필터링하는 방법을 보여줍니다.

예제 코드

import java.lang.StackWalker.StackFrame;
import java.util.*;
import java.util.stream.*;

public class StackWalkerFilterTest {
    public static void main(String args[]) {
        final List<Class> filterClasses = new ArrayList<>();
        filterClasses.add(StackWalkerFilterTest.class);

        System.out.println("--- filter Frame by Class >> get first matching frame ---");
        Optional<StackFrame> frameByClass = findFrameByClass(filterClasses);
        System.out.println(frameByClass.toString());

        System.out.println("--- filter Frame by Class >> get all matching frames ---");
        List<StackFrame> framesByClass = findAllFramesByClass(filterClasses);
        System.out.println(framesByClass);
    }
    private static Optional<StackFrame> findFrameByClass(List<Class> filterClasses) {
        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
.walk(s -> s.filter(f -> filterClasses.contains(f.getDeclaringClass())).findFirst());
    }
    private static List<StackFrame> findAllFramesByClass(List<Class> filterClasses) {
        return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).walk(
s -> s.filter(f -> filterClasses.contains(f.getDeclaringClass())).collect(Collectors.toList()));
    }
}

실행 결과

--- filter Frame by Class >> get first matching frame ---
Optional[StackWalkerTest.findFrameByClass(StackWalkerTest.java:20)]
--- filter Frame by Class >> get all matching frames ---
[StackWalkerTest.findAllFramesByClass(StackWalkerTest.java:23), StackWalkerTest2.main(StackWalkerTest.java:15)]

코드 설명

  • findFrameByClass(): walk() 메서드 내부에서 filter()로 조건에 맞는 프레임을 걸러낸 뒤, findFirst()를 호출하여 첫 번째 일치 프레임을 Optional 형태로 반환합니다.
  • findAllFramesByClass(): 동일한 방식으로 필터링한 후 collect(Collectors.toList())를 사용해 일치하는 모든 스택 프레임을 리스트로 수집합니다.
  • f.getDeclaringClass()를 통해 각 스택 프레임이 속한 클래스를 확인하고, 미리 정의된 filterClasses 목록과 비교합니다.

이처럼 StackWalker API를 활용하면 기존의 Thread.getStackTrace() 방식보다 효율적이고 유연하게 스택 프레임을 탐색하고 필터링할 수 있습니다.