java - print - thread stacktrace




스택 추적을 문자열로 변환하려면 어떻게해야합니까? (18)

구아바의 Throwables 클래스

실제 Throwable 인스턴스가있는 경우 Google GuavaThrowables.getStackTraceAsString() 제공합니다.

예:

String s = Throwables.getStackTraceAsString ( myException ) ;

Throwable.getStackTrace() 의 결과를 스택 트레이스를 나타내는 문자열로 변환하는 가장 쉬운 방법은 무엇입니까?


코 틀린

Throwable 클래스를 확장하면 String 속성 error.stackTraceString .

val Throwable.stackTraceString: String
  get() {
    val sw = StringWriter()
    val pw = PrintWriter(sw)
    this.printStackTrace(pw)
    return sw.toString()
  }

Android 용으로 개발하는 경우 훨씬 쉬운 방법은 다음과 같습니다.

import android.util.Log;

String stackTrace = Log.getStackTraceString(exception); 

형식은 getStacktrace와 동일합니다 (예 :

09-24 16:09:07.042: I/System.out(4844): java.lang.NullPointerException
09-24 16:09:07.042: I/System.out(4844):   at com.temp.ttscancel.MainActivity.onCreate(MainActivity.java:43)
09-24 16:09:07.042: I/System.out(4844):   at android.app.Activity.performCreate(Activity.java:5248)
09-24 16:09:07.043: I/System.out(4844):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread.access$800(ActivityThread.java:139)
09-24 16:09:07.043: I/System.out(4844):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
09-24 16:09:07.043: I/System.out(4844):   at android.os.Handler.dispatchMessage(Handler.java:102)
09-24 16:09:07.043: I/System.out(4844):   at android.os.Looper.loop(Looper.java:136)
09-24 16:09:07.044: I/System.out(4844):   at android.app.ActivityThread.main(ActivityThread.java:5097)
09-24 16:09:07.044: I/System.out(4844):   at java.lang.reflect.Method.invokeNative(Native Method)
09-24 16:09:07.044: I/System.out(4844):   at java.lang.reflect.Method.invoke(Method.java:515)
09-24 16:09:07.044: I/System.out(4844):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
09-24 16:09:07.044: I/System.out(4844):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)

Gala의 대답에 대한 예외는 예외의 원인도 포함합니다.

private String extrapolateStackTrace(Exception ex) {
    Throwable e = ex;
    String trace = e.toString() + "\n";
    for (StackTraceElement e1 : e.getStackTrace()) {
        trace += "\t at " + e1.toString() + "\n";
    }
    while (e.getCause() != null) {
        e = e.getCause();
        trace += "Cause by: " + e.toString() + "\n";
        for (StackTraceElement e1 : e.getStackTrace()) {
            trace += "\t at " + e1.toString() + "\n";
        }
    }
    return trace;
}

stacktrace를 PrintStream으로 인쇄 한 다음 문자열로 변환합니다.

// ...

catch (Exception e)
{
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    e.printStackTrace(new PrintStream(out));
    String str = new String(out.toByteArray());

    System.out.println(str);
}

경고 : 원인을 포함하지 않습니다 (보통 유용한 비트입니다!).

public String stackTraceToString(Throwable e) {
    StringBuilder sb = new StringBuilder();
    for (StackTraceElement element : e.getStackTrace()) {
        sb.append(element.toString());
        sb.append("\n");
    }
    return sb.toString();
}

나를 위해 가장 깨끗하고 쉬운 방법은 다음과 같습니다.

import java.util.Arrays;
Arrays.toString(e.getStackTrace());


다음은 코드에 직접 복사하여 붙여 넣을 수있는 버전입니다.

import java.io.StringWriter; 
import java.io.PrintWriter;

//Two lines of code to get the exception into a StringWriter
StringWriter sw = new StringWriter();
new Throwable().printStackTrace(new PrintWriter(sw));

//And to actually print it
logger.info("Current stack trace is:\n" + sw.toString());

또는 catch 블록에서

} catch (Throwable t) {
    StringWriter sw = new StringWriter();
    t.printStackTrace(new PrintWriter(sw));
    logger.info("Current stack trace is:\n" + sw.toString());
}


스택 트레이스를 동봉 한 멀티 라인 문자열로 변환하는 나의 oneliner :

Stream.of(e.getStackTrace()).map((a) -> a.toString()).collect(Collectors.joining("\n", "[", "]"))

로거를 "있는 그대로"전달하기 쉽습니다.


예외 스택을 표시하려면 exp.printStackTrace() 를 사용하십시오.

try {
   int zero = 1 - 1;
   int a = 1/zero;
} catch (Exception e) {
    e.printStackTrace();
}

이전 질문이지만, 특정 클래스 나 패키지를 제외하고 실제로 관심이없는 부분을 제거하여 모든 스택을 인쇄하고 싶지 않은 특별한 경우를 추가하고 싶습니다 .

PrintWriter 대신 SelectivePrintWriter 사용하십시오.

// This filters out this package and up.
String packageNameToFilter = "org.springframework";

StringWriter sw = new StringWriter();
PrintWriter pw = new SelectivePrintWriter(sw, packageNameToFilter);
e.printStackTrace(pw);
String sStackTrace = sw.toString(); 
System.out.println(sStackTrace);

SelectivePrintWriter 클래스가 다음에 의해 제공되는 곳 :

public class SelectivePrintWriter extends PrintWriter {
    private boolean on = true;
    private static final String AT = "\tat";
    private String internal;

    public SelectivePrintWriter(Writer out, String packageOrClassName) {
        super(out);
        internal = "\tat " + packageOrClassName;
    }

    public void println(Object obj) {
        if (obj instanceof String) {
            String txt = (String) obj;
            if (!txt.startsWith(AT)) on = true;
            else if (txt.startsWith(internal)) on = false;
            if (on) super.println(txt);
        } else {
            super.println(obj);
        }
    }
}

이 클래스는 Regex, contains 또는 다른 기준에 따라 쉽게 제외 될 수 있습니다. 또한 Throwable 구현 세부 사항 (변경 가능성은 없지만 여전히)에 따라 달라집니다.


첫 번째 의견에서 영리한 저격은 매우 재미 있었지만 실제로 무엇을하려고하는지에 달려 있습니다. 올바른 라이브러리가 없다면 3 줄의 코드 (D. Wroblewski의 답변과 같이)가 완벽합니다. OTOH, 만약 당신이 이미 apache.commons 라이브러리를 가지고 있다면 (대부분의 대규모 프로젝트들이 그렇듯이) Amar의 대답은 더 짧습니다. 라이브러리를 가져 와서 제대로 설치하는 데 10 분이 걸릴 수 있습니다 (수행중인 작업을 아는 경우 1 개 미만). 그러나 시계가 똑딱 거리고 있으므로 여분의 시간을 갖지 못할 수도 있습니다. Jarek Przygódzki는 "중첩 예외가 필요하지 않은 경우"라는 흥미로운 경고를했습니다.

하지만 스택 트레이스 필요하다면 중첩 된 것일까? 이 경우 비밀은 apache.common의 getFullStackTrace를 사용하는 것입니다 ( http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html#getFullStackTrace%28java.lang.Throwable%29 참조) http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html#getFullStackTrace%28java.lang.Throwable%29 )

그것은 나의 베이컨을 구했다. 감사, Amar, 힌트를 위해!


Android 용으로 개발하지 않고 외부 라이브러리를 사용하고 싶지 않은 경우 다음과 같이 '확장'메소드를 만들 수 있습니다.

public static String getStackTraceString(Throwable e) {
    return getStackTraceString(e, "");
}

private static String getStackTraceString(Throwable e, String indent) {
    StringBuilder sb = new StringBuilder();
    sb.append(e.toString());
    sb.append("\n");

    StackTraceElement[] stack = e.getStackTrace();
    if (stack != null) {
        for (StackTraceElement stackTraceElement : stack) {
            sb.append(indent);
            sb.append("\tat ");
            sb.append(stackTraceElement.toString());
            sb.append("\n");
        }
    }

    Throwable[] suppressedExceptions = e.getSuppressed();
    // Print suppressed exceptions indented one level deeper.
    if (suppressedExceptions != null) {
        for (Throwable throwable : suppressedExceptions) {
            sb.append(indent);
            sb.append("\tSuppressed: ");
            sb.append(getStackTraceString(throwable, indent + "\t"));
        }
    }

    Throwable cause = e.getCause();
    if (cause != null) {
        sb.append(indent);
        sb.append("Caused by: ");
        sb.append(getStackTraceString(cause, indent));
    }

    return sb.toString();
}

Throwable.printStackTrace (PrintWriter pw) 를 사용해 스택 트레이스를 적절한 라이터에 송신합니다.

import java.io.StringWriter;
import java.io.PrintWriter;

// ...

StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
String sStackTrace = sw.toString(); // stack trace as a string
System.out.println(sStackTrace);

Apache Commons Lang 3.4 ( JavaDoc )의 코드 :

public static String getStackTrace(final Throwable throwable) {
    final StringWriter sw = new StringWriter();
    final PrintWriter pw = new PrintWriter(sw, true);
    throwable.printStackTrace(pw);
    return sw.getBuffer().toString();
}

다른 답변과의 차이점은 PrintWriter autoFlush사용 한다는 입니다.


Arrays.toString(thrown.getStackTrace())

결과를 문자열로 변환하는 가장 쉬운 방법은 내 프로그램에서 스택 추적을 인쇄하는 데 사용하고 있습니다.

LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});




tostring