티스토리 뷰

Java & Kotlin

[Java] 에러 스택 트레이스 최적화를 도와주는 -XX:+OmitStackTraceInFastThrow(사라진 예외 스택 트레이스)

망나니개발자 2026. 8. 4. 10:00
반응형

 

 

1. 에러 스택 트레이스 최적화를 도와주는
-XX:+OmitStackTraceInFastThrow(사라진 예외 스택 트레이스)


[ OmitStackTraceInFastThrow 옵션이란? ]

-XX:+OmitStackTraceInFastThrow 옵션은 JVM이 동일한 위치에서 반복해서 예외를 던질 경우, JIT 컴파일러가 스택트레이스와 메시지가 없는 싱글턴 예외로 바꿔 던지는 최적화 기법이다. 이는 JDK 1.4부터 기본 활성화되어 있는 상태이다.

예외 생성 비용의 대부분은 fillInStackTrace() 메서드로 콜스택을 훑어 프레임 배열을 만드는 작업이다. 스택이 깊으면 예외 하나당 수 ms씩 소요되곤 하는데, 같은 지점에서 뻔한 예외가 수천 번 반복되면 매번 스택을 뜨는게 낭비이다. 따라서 JIT이 그 메서드를 재컴파일하면서 미리 만들어 둔 예외 인스턴스를 던지도록 바꾼다.

 

 

 

[ OmitStackTraceInFastThrow 최적화의 대상 ]

이 최적화는 직접 new로 만들어 던지는 예외는 영향을 받지 않는다. 참고로 해당 예외는 JVM이 암묵적으로 던지는 예외만 해당한다. 이때 “JVM이 암묵적으로 던지는 예외”란, 바이트코드 내부에서 던져지는 예외라고 보면 된다. 다음의 Run-time Exception에 대한 정리를 보면, “어떤 명령어(instruction)의 실행으로 인해 런타임 예외가 발생할 수 있는 경우”가 존재함을 알 수 있다.

 

 

 

그리고 바이트코드에 대한 정의서를 보면, 각 바이트코드에 따라 Run-time Exception 필드가 존재하는데, 바이트코드 내부에서 던져지는 예외를 정의하고 있다.

그리고 여기서 얘기하는 “JVM이 암묵적으로 던지는 예외”란, 바로 바이트코드 명령어가 직접 던지는 예외를 의미하는 것이다.

 

 

 

[ 재현해보기 ]

다음의 간단한 코드로 문제 상황을 재현해볼 수 있다.

/**
 * 같은 자리에서 JVM 이 던지는 예외가 반복되면, JIT 이 스택트레이스와 메시지가 없는 예외로 바꿔 던진다. 이 옵션은 JVM 기본값이 true 라 별도 설정 없이 동작한다.
 *   java FastThrow.java
 *   java -XX:-OmitStackTraceInFastThrow FastThrow.java
 */
public class FastThrow {

    static final int[] arr = new int[10];

    public static void main(String[] args) {
        for (int i = 1; i <= 100_000; i++) {
            try {
                int x = arr[100];                  // 항상 범위를 벗어난다
            } catch (ArrayIndexOutOfBoundsException e) {
                if (e.getStackTrace().length == 0) {
                    System.out.printf("%,d 회째: 스택트레이스 사라짐, message=%s%n", i, e.getMessage());
                    return;
                }
                if (i == 1) {
                    System.out.printf("%,d 회째: 스택 %d줄, message=%s%n",
                            i, e.getStackTrace().length, e.getMessage());
                }
            }
        }
        System.out.println("10만 회까지 스택트레이스 유지됨");
    }
}

 

 

참고로 이때 임계치는 코드 구조와 JIT 컴파일 시점에 좌우된다. 같은 코드를 같은 JVM에서 돌리면 재현되지만, 코드가 조금만 달라져도 크게 바뀐다. 절대적인 기준값이 있는 게 아니다.

만약 이미 JIT 컴파일이 되어 있는 경우에는, 같은 지점 트랩이 PerBytecodeTrapLimit(기본 4) 만큼만 쌓이면 바로 전환된다. 위에서는 4만 회를 넘게 해야 최적화가 진행되는데, 이는 JIT 컴파일 자체를 기다린 시간이 대부분이라고 볼 수 있다.

 

 

 

참고자료

 

 

 

 

반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2026/08   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
글 보관함