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() 메소드를 사용하여 출력하는 방법에 대해 알아보았습니다 . 또한 Thread 및 Throwable 클래스 를 사용하여 현재 스택 추적을 얻는 방법도 살펴보았습니다 .
항상 그렇듯이 이 기사의 전체 코드 샘플은 GitHub 에서 찾을 수 있습니다 .