1. 개요

Java 개발자로서 예외 를 처리할 때 스택 추적의 개념을 접하는 것은 매우 일반적 입니다.

이 사용방법(예제)에서는 스택 추적이 무엇이며 프로그래밍/디버깅하는 동안 스택 추적을 사용하는 방법을 이해합니다. 또한 StackTraceElement 클래스도 살펴볼 것입니다. 마지막으로 Thread 및  Throwable 클래스를 사용하여 가져오는 방법을 배웁니다.

2. 스택 추적이란 무엇입니까?

역추적이라고도 하는 스택 추적은 스택 프레임 List입니다. 간단히 말해서 이러한 프레임은 프로그램 실행 중 순간을 나타냅니다.

스택 프레임 에는 코드가 호출한 메서드에 대한 정보가 포함 됩니다. 현재 메서드에서 시작하여 프로그램이 시작된 시점까지 확장되는 프레임 List입니다.

이를 더 잘 이해하기 위해 예외 후 현재 스택 추적을 덤프한 간단한 예를 살펴보겠습니다.

public class DumpStackTraceDemo 
{ 
    public static void main(String[] args) {
        methodA(); 
    } 

    public static void methodA() {
        try {
            int num1 = 5/0; // java.lang.ArithmeticException: divide by zero
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

위의 예에서 methodA() 는 ArithmeticException을 발생 시키고, 이는 catch 블록에서 현재 스택 추적을 덤프합니다.

java.lang.ArithmeticException: / by zero
at main.java.com.baeldung.tutorials.DumpStackTraceDemo.methodA(DumpStackTraceDemo.java:11)
at main.java.com.baeldung.tutorials.DumpStackTraceDemo.main(DumpStackTraceDemo.java:6)

3. StackTraceElement  클래스

스택 추적은 StackTraceElement 클래스의 요소로 구성됩니다. 다음 메서드를 사용하여 각각 클래스 및 메서드 이름을 가져올 수 있습니다.

  • getClassName – 현재 실행 지점을 포함하는 클래스의 정규화된 이름을 반환합니다.
  • getMethodName – 이 스택 추적 요소가 나타내는 실행 지점을 포함하는 메서드의 이름을 반환합니다.

Java API 설명서 의 StackTraceElement 클래스에서 전체 메서드 List과 해당 세부 정보를 볼 수 있습니다 .

4. 스레드 클래스 를 사용하여 스택 추적 가져오기

Thread 인스턴스 에서 getStackTrace() 메서드를 호출하여 스레드에서 스택 추적을 얻을 수 있습니다  . 스레드의 스택 프레임에 대한 세부 정보를 찾을 수 있는 StackTraceElement 배열을 반환합니다 .

예를 보자:

public class StackTraceUsingThreadDemo {

    public static void main(String[] args) {
        methodA();
    }
    
    public static StackTraceElement[] methodA() {
        return methodB();
    }

    public static StackTraceElement[] methodB() {
        Thread thread = Thread.currentThread();
        return thread.getStackTrace();
    }
}

위의 클래스에서 메소드 호출은 main() -> methodA() -> methodB() -> getStackTrace() 방식으로 발생합니다.

테스트 케이스 메서드가 methodA() 를 호출하는 다음 테스트 케이스로 이를 확인해보자 .

@Test
public void whenElementIsFetchedUsingThread_thenCorrectMethodAndClassIsReturned() {
    StackTraceElement[] stackTrace = new StackTraceUsingThreadDemo().methodA();
    
    StackTraceElement elementZero = stackTrace[0];
    assertEquals("java.lang.Thread", elementZero.getClassName());
    assertEquals("getStackTrace", elementZero.getMethodName());
    
    StackTraceElement elementOne = stackTrace[1];
    assertEquals("com.baeldung.tutorials.StackTraceUsingThreadDemo", elementOne.getClassName());
    assertEquals("methodB", elementOne.getMethodName());
    
    StackTraceElement elementTwo = stackTrace[2];
    assertEquals("com.baeldung.tutorials.StackTraceUsingThreadDemo", elementTwo.getClassName());
    assertEquals("methodA", elementTwo.getMethodName());
    
    StackTraceElement elementThree = stackTrace[3];
    assertEquals("test.java.com.baeldung.tutorials.CurrentStacktraceDemoUnitTest", elementThree.getClassName());
    assertEquals("whenElementIsFetchedUsingThread_thenCorrectMethodAndClassIsReturned", elementThree.getMethodName());
}

위의 테스트 케이스에서는 StackTraceUsingThreadDemo 클래스 의 methodB()를 사용하여 StackTraceElement 의 배열을 가져왔습니다. 그런 다음 StackTraceElement 클래스의 getClassName()getMethodName()  메서드를 사용하여 스택 추적에서 메서드 및 클래스 이름을 확인합니다 .

5. Throwable 클래스 를 사용하여 스택 추적 가져 오기

Java 프로그램이 Throwable 객체를 던질 때 단순히 콘솔에 출력하거나 로깅하는 대신 getStackTrace() 메서드  를 호출하여  StackTraceElement 객체 배열을 얻을 수 있습니다 .

예를 살펴보겠습니다.

public class StackTraceUsingThrowableDemo {
    
    public static void main(String[] args) {
        methodA(); 
    } 

    public static StackTraceElement[] methodA() {
        try {
            methodB();
        } catch (Throwable t) {
            return t.getStackTrace();
        }
        return null;
    }

    public static void methodB() throws Throwable {
        throw new Throwable("A test exception");
    }
}

여기서 메서드 호출은 main() -> methodA() -> methodB() -> getStackTrace() 방식으로 발생합니다.

테스트를 통해 확인해보자:

@Test
public void whenElementIsFecthedUsingThrowable_thenCorrectMethodAndClassIsReturned() {
    StackTraceElement[] stackTrace = new StackTraceUsingThrowableDemo().methodA();

    StackTraceElement elementZero = stackTrace[0];
    assertEquals("com.baeldung.tutorials.StackTraceUsingThrowableDemo", elementZero.getClassName());
    assertEquals("methodB", elementZero.getMethodName());

    StackTraceElement elementOne = stackTrace[1];
    assertEquals("com.baeldung.tutorials.StackTraceUsingThrowableDemo", elementOne.getClassName());
    assertEquals("methodA", elementOne.getMethodName());

    StackTraceElement elementThree = stackTrace[2];
    assertEquals("test.java.com.baeldung.tutorials.CurrentStacktraceDemoUnitTest", elementThree.getClassName());
    assertEquals("whenElementIsFecthedUsingThrowable_thenCorrectMethodAndClassIsReturned", elementThree.getMethodName());
}

위의 테스트 케이스에서는 StackTraceUsingThrowableDemo 클래스 의 methodB()를 사용하여 StackTraceElement 의 배열을 가져왔습니다. 그런 다음 StackTraceElement 클래스 의 배열에서 요소의 순서를 이해하기 위해 메서드 및 클래스 이름을 확인했습니다 .

6. 결론

이번 글에서는 자바 스택 트레이스에 대해 알아 보았고 , 예외 상황에서 printStackTrace() 메소드를 사용하여 출력하는 방법에 대해 알아보았습니다 . 또한 ThreadThrowable 클래스 를 사용하여 현재 스택 추적을 얻는 방법도 살펴보았습니다 .

항상 그렇듯이 이 기사의 전체 코드 샘플은  GitHub 에서 찾을 수 있습니다 .

Generic footer banner