Java에서 예외를 발생시키지 않고 스택 추적을 덤프하는 방법이 있습니까?


159

Java 응용 프로그램을위한 디버그 도구를 만들려고합니다.

Exception.printStackTrace()실제로 예외를 throw하지 않고 스택 추적을 얻을 수 있는지 궁금합니다 .

내 목표는 주어진 메소드에서 스택을 덤프하여 메소드 호출자가 누구인지 확인하는 것입니다.

답변:


84

또한 Thread.getAllStackTraces()살아있는 모든 스레드에 대한 스택 추적 맵을 얻으 려고 시도 할 수 있습니다 .


250

예, 간단히 사용하십시오

Thread.dumpStack()

44
...하지만 던지지는 않습니다.
— Rob

5
이것이 실제로 문제를 해결하는 답입니다.
— bruno

7
매우 간단하고 우아합니다. 이것은 받아 들여진 대답이어야합니다.
— deLock

11
이 방법의 근원 인 public static void dumpStack() { new Exception("Stack trace").printStackTrace(); }
— Fwiw

에 출력하는 것에 만족한다면 이것은 질문에 대한 가장 좋은 대답 stderr입니다.
— 마이크 설치류

46

Ram의 제안과 같이 시스템의 모든 스레드가 아닌 현재 스레드에 대한 추적을 원한다면 다음을 수행하십시오.

Thread.currentThread (). getStackTrace ()

발신자를 찾으려면 다음을 수행하십시오.

private String getCallingMethodName() {
    StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
    return callingFrame.getMethodName();
}

그리고 호출자가 누구인지 알아야하는 메소드 내에서 해당 메소드를 호출하십시오. 그러나 경고 단어 : 목록 내 호출 프레임의 색인은 JVM에 따라 다를 수 있습니다! 추적이 생성되는 지점에 도달하기 전에 getStackTrace 내에있는 호출 계층 수에 따라 다릅니다. 보다 강력한 솔루션은 추적을 가져 와서 getCallingMethodName에 대한 프레임을 찾은 후 반복하여 진정한 호출자를 찾기위한 것입니다.


2
따라서 새로운 예외를 직접 만들고 [1]을 색인으로 사용하십시오!
— Daniel

3
이 질문의 제목은 "예외를 던지지 않고"라고 말합니다. 물론 예외를 만들 것을 제안하지만 그것을 던지지 말 것을 제안하지만 여전히 질문의 정신에 있지 않다고 생각합니다.
— 톰 앤더슨

1
당연하지. 예외를 만드는 것이 스택 트레이스를 얻는 가장 낮은 수준의 방법입니다. 심지어 Thread.currentThread (). getStackTrace ()조차도 그렇게하지만 내 길은 더 빠릅니다 :).
— Daniel

@Daniel 또 다른 고려 사항이 있습니다 : Spock과 같은 많은 테스트 프레임 워크를 사용하면 예외를 throw하지 않고 예외를 생성하는 것만으로 충분합니다. 테스트는 예외가 "발생"한 것으로 간주하고 테스트는 실패로 끝납니다.
— mike rodent

@ mikerodent : 확실합니까? Spock은 에이전트를 사용해야합니다. 그러나 어쨌든 클래스를 호출해야하기 때문에 유틸리티 함수에 Reflection.getCallerClass (2)를 사용했습니다. 그런 식으로 함수와 줄 번호를 얻지 못할 것이라고 생각했습니다.
— Daniel

37

다음과 같은 스택 추적을 얻을 수 있습니다.

Throwable t = new Throwable();
t.printStackTrace();

프레임에 액세스하려면 t.getStackTrace ()를 사용하여 스택 프레임의 배열을 얻을 수 있습니다.

핫스팟 컴파일러가 작업 최적화에 바쁘면이 스택 추적 (다른 것과 마찬가지로)에 일부 프레임이 누락 될 수 있습니다.


나는 출력을 지시 할 수있는 기회를 제공하기 때문에이 대답을 좋아합니다. 나는 대체 할 수 t.printStackTrace와 함께 t.printStackTrace(System.out).

4
한 줄로 :new Throwable().printStackTrace(System.out);

1
이것이 정답입니다. 간단하고 간단합니다! 공유해 주셔서 감사합니다
— Sam

2
그리고 java.util.Logger로 쉽게 보낼 수 있습니다log.log(Level.SEVERE, "Failed to do something", new Throwable());
— MitchBroadhead

13

Thread.dumpStack ()은 실제로 예외를 발생시킵니다.

new Exception("Stack trace").printStackTrace();

12
예외를 생성하지만 던지지는 않습니다.
— MatrixFrog

6

프로세스에 QUIT 신호를 보내 실행중인 Java 프로세스에서 Thread.getAllStackTraces ()를 실행하도록 신호를 JVM에 보낼 수도 있습니다.

유닉스 / 리눅스에서 :

kill -QUIT process_id여기서 process_id는 Java 프로그램의 프로세스 번호입니다.

Windows에서는 콘솔 프로세스를 실행하지 않으면 일반적으로 표시되지 않지만 응용 프로그램에서 Ctrl-Break를 누를 수 있습니다.

JDK6에는 컴퓨터에서 실행중인 JDK6 프로세스의 스택을 표시하는 또 다른 옵션 인 jstack 명령이 도입되었습니다.

jstack [-l] <pid>

이 옵션은 프로덕션 환경에서 실행되고 쉽게 수정할 수없는 응용 프로그램에 매우 유용합니다. 런타임 교착 상태 또는 성능 문제를 진단하는 데 특히 유용합니다.

http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/ http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html


6

캡처 출력이 필요한 경우

StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();

6

자바 9는 StackWalker 는 스택을 걷기위한 클래스 및 지원 클래스를 .

다음은 Javadoc의 일부 스 니펫입니다.

이 walk메소드 StackFrames는 현재 스레드 에 대한 순차 스트림을 연 다음 주어진 함수를 적용하여 StackFrame스트림 을 걷습니다 . 스트림은 스택이 생성 된 실행 지점을 나타내는 최상위 최상위 프레임부터 최상위 프레임까지 순서대로 스택 프레임 요소를보고합니다. StackFrame스트림은 때 도보 메소드가 반환을 닫힙니다. 닫힌 스트림을 재사용하려고하면 처리 IllegalStateException됩니다.

...

  1. 현재 스레드의 상위 10 개 스택 프레임을 스냅 샷하려면

    List<StackFrame> stack = StackWalker.getInstance().walk(s ->
     s.limit(10).collect(Collectors.toList()));

0

HPROF 자바 프로파일 러

코드 에서이 작업을 수행 할 필요조차 없습니다. Java HPROF를 프로세스에 연결하고 언제든지 Control- \를 눌러 힙 덤프, 실행중인 스레드 등을 출력 할 수 있습니다. . . 응용 프로그램 코드를 정리하지 않고. 이것은 약간 구식이지만 Java 6에는 GUI jconsole이 제공되지만 여전히 HPROF가 매우 유용하다는 것을 알았습니다.


0

Rob Di Marco 의 답변 은 (으)로 출력하기에 가장 좋습니다 stderr.

String일반 추적에 따라 새 줄 을 사용하여를 캡처하려면 다음을 수행하십시오.

Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.