1. 스택 트레이스 얻기

스택 추적 가져오기

Java 프로그래밍 언어는 프로그래머가 프로그램에서 일어나는 일에 대한 정보를 얻을 수 있는 다양한 방법을 제공합니다. 그리고 단지 단어가 아닙니다.

예를 들어, C++ 프로그램이 컴파일된 후에는 기계 코드로 가득 찬 하나의 큰 파일이 되고 런타임에 프로그래머가 사용할 수 있는 것은 현재 실행 중인 기계 코드가 포함된 메모리 블록의 주소뿐입니다. 많이는 아닙니다.

그러나 Java의 경우 프로그램이 컴파일된 후에도 클래스는 클래스로 남아 있고 메서드와 변수는 사라지지 않으며 프로그래머는 프로그램에서 일어나는 일에 대한 정보를 얻을 수 있는 여러 가지 방법이 있습니다.

스택 추적

예를 들어 프로그램 실행 시점에서 현재 실행 중인 메서드의 클래스와 이름을 찾을 수 있습니다. 그리고 하나의 메서드만이 아니라 현재 메서드에서 다시 메서드로 메서드 호출의 전체 체인에 대한 정보를 얻을 수 있습니다 main().

현재 메서드, 이를 호출한 메서드, 해당 메서드를 호출한 메서드 등으로 구성된 목록을 스택 추적 이라고 합니다 . 다음 문장으로 얻을 수 있습니다.

StackTraceElement[] methods = Thread.currentThread().getStackTrace();

두 줄로 작성할 수도 있습니다.

Thread current = Thread.currentThread();
StackTraceElement[] methods = current.getStackTrace();

currentThread()클래스의 정적 메서드 는 현재 스레드, 즉 현재 실행 스레드에 대한 정보를 포함하는 개체 Thread에 대한 참조를 반환합니다 . Java CoreThread 퀘스트 의 레벨 17 및 18에서 스레드에 대해 자세히 알아볼 것입니다 .

이 개체 에는 메서드에 대한 정보가 포함된 개체 배열을 반환하는 메서드가 Thread있습니다 . 종합하면 이러한 모든 요소가 스택 추적을 형성합니다 .getStackTrace()StackTraceElement

예:

암호
public class Main
{
   public static void main(String[] args)
   {
      test();
   }

   public static void test()
   {
      Thread current = Thread.currentThread();
      StackTraceElement[] methods = current.getStackTrace();

      for(var info: methods)
         System.out.println(info);
   }
}
콘솔 출력
java.base/java.lang.Thread.getStackTrace(Thread.java:1606)
Main.test(Main.java:11)
Main.main(Main.java:5)

예제의 콘솔 출력에서 ​​볼 수 있듯이 getStackTrace()메서드는 세 가지 요소의 배열을 반환했습니다.

  • getStackTrace()Thread수업 방식
  • test()Main수업 방식
  • main()Main수업 방식

이 스택 추적에서 다음과 같은 결론을 내릴 수 있습니다.

  • 이 메소드는 Main.java 파일의 11행에 있는 메소드 Thread.getStackTrace()에 의해 호출되었습니다.Main.test()
  • 메서드 는 Main.java 파일의 5행에 있는 메서드 Main.test()에 의해 호출되었습니다.Main.main()
  • 아무도 메서드를 호출하지 않았습니다 Main.main(). 이것은 호출 체인의 첫 번째 메서드입니다.

그건 그렇고, 사용 가능한 정보 중 일부만 화면에 표시되었습니다. StackTraceElement다른 모든 것은 개체 에서 직접 얻을 수 있습니다.



2.StackTraceElement

이름에서 알 수 있듯이 이 StackTraceElement클래스는 스택 추적 요소, 즉 stack trace.

이 클래스에는 다음과 같은 인스턴스 메서드가 있습니다.

방법 설명
String getClassName()
클래스의 이름을 반환
String getMethodName()
메서드의 이름을 반환
String getFileName()
파일 이름을 반환합니다(하나의 파일에 여러 클래스가 포함될 수 있음).
int getLineNumber()
메서드가 호출된 파일의 줄 번호를 반환합니다.
String getModuleName()
모듈의 이름을 반환합니다(일 수 있음 null).
String getModuleVersion()
모듈의 버전을 반환합니다(일 수 있음 null).

현재 호출 스택에 대한 보다 완전한 정보를 얻는 데 도움이 될 수 있습니다.

암호 콘솔 출력 메모
public class Main
{
   public static void main(String[] args)
   {
      test();
   }

   public static void test()
   {
      Thread current = Thread.currentThread();
      StackTraceElement[] methods = current.getStackTrace();

      for(StackTraceElement info: methods)
      {
         System.out.println(info.getClassName());
         System.out.println(info.getMethodName());

         System.out.println(info.getFileName());
         System.out.println(info.getLineNumber());

         System.out.println(info.getModuleName());
         System.out.println(info.getModuleVersion());
         System.out.println();
      }
   }
}
java.lang.Thread
getStackTrace
Thread.java
1606
java.base
11.0.2

Main
test
Main.java
11
null
null

Main
main
Main.java
5
null
null
클래스 이름
메서드 이름
파일 이름
줄 번호
모듈 이름
모듈 버전

클래스
이름 메서드 이름
파일 이름
줄 번호 모듈
이름
모듈 버전

클래스 이름
메서드 이름 파일
이름
줄 번호 모듈
이름
모듈 버전


3. 스택

스택 추적 이 무엇인지 이미 알고 있지만 스택 (Stack 클래스) 이 무엇입니까 ?

스택은 요소를 추가하고 요소를 검색할 수 있는 데이터 구조입니다. 이렇게 하면 끝에서 요소만 가져올 수 있습니다. 먼저 마지막으로 추가된 요소를 가져온 다음 두 번째에서 마지막으로 추가된 요소를 가져옵니다.

이름 스택 자체는 종이 더미와 상호 작용하는 방식과 같은 이 동작을 제안합니다. 시트 1, 2, 3을 스택에 넣으면 역순으로 회수해야 합니다. 먼저 세 번째 시트, 그 다음 두 번째 시트, 그리고 첫 번째 시트만.

Java에는 동일한 이름과 동작을 가진 특별한 Stack 컬렉션 클래스도 있습니다. ArrayList이 클래스는 및 와 많은 동작을 공유합니다 LinkedList. 그러나 스택 동작을 구현하는 메서드도 있습니다.

행동 양식 설명
T push(T obj)
obj스택의 맨 위에 요소를 추가합니다.
T pop()
스택의 맨 위에서 요소를 가져옵니다(스택 깊이가 감소함).
T peek()
스택의 맨 위에 있는 항목을 반환합니다(스택은 변경되지 않음).
boolean empty()
컬렉션이 비어 있는지 확인
int search(Object obj)
컬렉션에서 개체를 검색하고 해당 개체를 반환합니다.index

예:

암호 스택 내용(스택의 맨 위는 오른쪽에 있음)
Stack<Integer> stack = new Stack<Integer>();
stack.push(1);
stack.push(2);
stack.push(3);
int x = stack.pop();
stack.push(4);
int y = stack.peek();
stack.pop();
stack.pop();

[1]
[1, 2]
[1, 2, 3]
[1, 2]
[1, 2, 4]
[1, 2, 4]
[1, 2]
[1]

스택은 프로그래밍에서 꽤 자주 사용됩니다. 그래서 이것은 유용한 컬렉션입니다.



4. 예외 처리 중 스택 추적 표시

메서드 호출 목록을 스택 추적 이라고 하는 이유는 무엇입니까 ? 메서드 목록을 메서드 이름이 있는 종이 더미로 생각하면 다음 메서드를 호출할 때 해당 메서드 이름이 있는 시트를 스택에 추가하기 때문입니다. 그리고 다음 종이가 그 위에 얹혀집니다.

메서드가 끝나면 스택 맨 위에 있는 시트가 제거됩니다. 그 위의 모든 시트를 제거하지 않고 스택 중간에서 시트를 제거할 수 없습니다. 마찬가지로 호출한 모든 메서드를 종료하지 않고 일련의 호출 도중에 메서드를 종료할 수 없습니다.

예외

스택의 또 다른 흥미로운 용도는 예외 처리 중에 있습니다.

프로그램에서 오류가 발생하고 예외가 발생하면 예외에는 현재 스택 추적이 포함됩니다 . 이 스택은 기본 메서드에서 시작하여 오류가 발생한 메서드로 끝나는 메서드 목록 으로 구성된 배열입니다. 예외가 발생한 줄도 있습니다!

이 스택 추적은 예외 내부에 저장되며 다음 방법을 사용하여 쉽게 검색할 수 있습니다.StackTraceElement[] getStackTrace()

예:

암호 메모
try
{
   // An exception may occur here
}
catch(Exception e)
{
   StackTraceElement[] methods = e.getStackTrace()
}




Catch the exception

오류가 발생했을 때 존재했던 스택 추적을 가져옵니다.

이것은 클래스의 메서드 Throwable이므로 클래스의 모든 자손(즉, 모든 예외)이 메서드를 가집니다 getStackTrace(). 매우 편리하죠?

예외의 스택 추적 표시

그런데 이 Throwable클래스에는 예외 내부에 저장된 모든 스택 추적 정보를 표시하는 스택 추적 작업을 위한 또 다른 메서드가 있습니다. 라고 합니다 printStackTrace().

매우 편리하게 예외가 있으면 호출할 수 있습니다.

예:

암호
try
{
   // An exception may occur here
}
catch(Exception e)
{
   e.printStackTrace();
}
콘솔 출력
java.base/java.lang.Thread.getStackTrace(Thread.java:1606)
Main.test(Main.java:11)
Main.main(Main.java:5)