programing

Java / Android - 전체 스택 트레이스를 인쇄하는 방법

newsource 2022. 10. 6. 22:01

Java / Android - 전체 스택 트레이스를 인쇄하는 방법

Android(Java)에서 전체 스택 트레이스를 인쇄하려면 어떻게 해야 합니까?응용 프로그램이 null Pointer에서 크래시하는 경우예외 같은 경우는 다음과 같이 (거의) 풀스택 트레이스를 출력합니다.

java.io.IOException: Attempted read from closed stream.
com.android.music.sync.common.SoftSyncException: java.io.IOException: Attempted read from closed stream.
    at com.android.music.sync.google.MusicSyncAdapter.getChangesFromServerAsDom(MusicSyncAdapter.java:545)
    at com.android.music.sync.google.MusicSyncAdapter.fetchDataFromServer(MusicSyncAdapter.java:488)
    at com.android.music.sync.common.AbstractSyncAdapter.download(AbstractSyncAdapter.java:417)
    at com.android.music.sync.common.AbstractSyncAdapter.innerPerformSync(AbstractSyncAdapter.java:313)
    at com.android.music.sync.common.AbstractSyncAdapter.onPerformLoggedSync(AbstractSyncAdapter.java:243)
    at com.google.android.common.LoggingThreadedSyncAdapter.onPerformSync(LoggingThreadedSyncAdapter.java:33)
    at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:164)
Caused by: java.io.IOException: Attempted read from closed stream.
    at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:148)
    at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:159)
    at java.util.zip.GZIPInputStream.readFully(GZIPInputStream.java:212)
    at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:81)
    at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:64)
    at android.net.http.AndroidHttpClient.getUngzippedContent(AndroidHttpClient.java:218)
    at com.android.music.sync.api.MusicApiClientImpl.createAndExecuteMethod(MusicApiClientImpl.java:312)
    at com.android.music.sync.api.MusicApiClientImpl.getItems(MusicApiClientImpl.java:588)
    at com.android.music.sync.api.MusicApiClientImpl.getTracks(MusicApiClientImpl.java:638)
    at com.android.music.sync.google.MusicSyncAdapter.getChangesFromServerAsDom(MusicSyncAdapter.java:512)
    ... 6 more

단, 디버깅을 위해 코드 내의 현재 위치에서 완전한 스택트레이스를 기록할 수 있습니다.난 그냥 이렇게 할 수 있을 것 같았어

StackTraceElement trace = new Exception().getStackTrace();
Log.d("myapp", trace.toString());

하지만 이건 포인터만 출력하면...모든 스택 트레이스 요소를 인쇄하기 위해 반복해야 합니까?아니면 간단하게 출력할 수 있는 방법이 있을까요?

다음 사항이 효과적입니다.

Log.d("myapp", Log.getStackTraceString(new Exception()));

주의:...x more는 스택 트레이스에서 정보를 절단하지 않습니다.

(는 이 예외에 대한 스택트레이스의 나머지 부분이 이 예외에 의해 발생한 예외의 스택트레이스 하단에서 지정된 프레임 수와 일치함을 나타냅니다).

...또는 바꿔 말하면,x more마지막과 함께x첫 번째 예외의 행.

모든 로그 메서드의 덮어쓰기가 있습니다.(String tag, String msg, Throwable tr)시그니처.

번째 파라미터로 예외를 전달하면 logcat의 완전한 스택트레이스가 표시됩니다.

Log.getStackTraceString(Throwable t)을 사용합니다.더 깊이 파고들면 더 긴 스택 트레이스를 얻을 수 있습니다.예를 들어 다음과 같습니다.

try {
    ...
} catch(Exception e) {
    Log.d("Some tag", Log.getStackTraceString(e.getCause().getCause()));
}

http://developer.android.com/reference/android/util/Log.html#getStackTraceString%28java.lang.Throwable%29에서 취득.

private static String buildStackTraceString(final StackTraceElement[] elements) {
    StringBuilder sb = new StringBuilder();
    if (elements != null && elements.length > 0) {
        for (StackTraceElement element : elements) {
            sb.append(element.toString());
        }
    }
    return sb.toString();
}


// call this at your check point
Log.d(TAG, buildStackTraceString(Thread.currentThread().getStackTrace()));

다음을 사용할 수 있습니다.

public static String toString(StackTraceElement[] stackTraceElements) {
    if (stackTraceElements == null)
        return "";
    StringBuilder stringBuilder = new StringBuilder();
    for (StackTraceElement element : stackTraceElements)
        stringBuilder.append(element.toString()).append("\n");
    return stringBuilder.toString();
}

다음과 같은 방법을 사용하여 앱 코드의 임의의 지점에서 스택 트레이스를 인쇄할 수도 있습니다.Thread.dumpStack()

자세한 내용은 링크를 참조하십시오.

완전한 stackTrace를 얻으려면 Throwable Object를 사용해야 합니다.

try{
 // code here
}catch(Exception e){
    String exception = getStackTrace(e);
}

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();
}

참고 자료: https://stackoverflow.com/a/18546861

이제 던질 수 있고 던질 수 있는.getCause()를 반복하는 재귀 함수를 실행했습니다.

이는 모든 "throwable.getCause()"가 일부 행과 새 행을 반복하여 새로운 예외 메시지를 반환하기 때문입니다.즉, '원인'이 있을 경우 'n more'와 같은 행이 있습니다."n more..."가 붙은 줄 앞에 마지막 줄을 붙일게요.그 후 원인 메시지가 표시되고 마지막으로 원인 메시지가 표시되는 것은 마지막 반복 행 뒤의 부분뿐입니다(두 행에 모두 표시되는 마지막 행: 주요 투척 가능과 투척 가능).

그 후 원인 메시지를 받았을 때 재귀를 사용하기 때문에 동일한 함수를 호출하여 메인 슬로우 가능에서 원인 메시지를 가져오면 이미 교체된 메시지가 나타납니다.메인 슬로우 가능의 원인에도 다른 원인이 있어 메인 슬로우 가능에는 3가지 레벨(메인 -> 원인 -> 원인)이 있는 경우, 메인 슬로우 가능에는 이미 교환된 메시지(메인 개념의 사용)가 표시됩니다.

public static <T extends Throwable> String printStackTraceString(T ex) {     // Recursive
    Throwable tr = ex;
    if (tr != null) {
        String st = Log.getStackTraceString(tr);
        if (tr.getCause() != null) {
            // Recursion...
            String cs = printStackTraceString(tr.getCause());

            String r1 = st.subSequence(0x0, st.lastIndexOf("\n", st.lastIndexOf("\n") - "\n".length())).toString();
            String replace = r1.substring(r1.lastIndexOf("\n"));
            if (cs.contains(replace)) {
                return r1.concat(cs.subSequence(cs.indexOf(replace) + replace.length(), cs.length()).toString());
            }
        }
        return st;
    }
    return "";
}

2레벨(메인->원인)만으로 시도했고, 그 이상으로는 시도하지 않았습니다:/ 잘못된 것이 있으면 함수를 편집하여 코멘트를 써주세요.d

좋은 코딩과 좋은 하루 되세요:d

중요:

이 코드는 "st"에 "\n" 또는 유사한 항목이 포함되지 않은 경우 예외가 발생할 수 있습니다(스택트레이스의 일부 예외에 문제가 있음을 발견했습니다).이 문제를 해결하려면 코드 행 앞에 "String r1 = ..." 검사를 추가해야 합니다.

"st"에 "\n"이 포함되어 있고 "st.subSequence"의 시작 인덱스와 끝 인덱스가 모두 유효한지 확인해야 합니다.

어쨌든, 이것을 트라이 캐치에 넣고, 예외의 경우는 빈 문자열을 반환하는 것을 추천합니다.(반환된 빈 문자열은 이전 처리 문자열에 연결되도록 재귀적입니다).

kotlin 안드로이드 사용자의 경우, kotlin에 의해 던질 수 있는 클래스에 내장된 스택 메시지 전체를 루프하기 위한 확장 기능을 만들 필요가 없습니다.

이것은 kotlin v > 1.4의 후드 아래에 있는 것입니다.

@SinceKotlin("1.4")
public actual fun Throwable.stackTraceToString(): String {
    val sw = StringWriter()
    val pw = PrintWriter(sw)
    printStackTrace(pw)
    pw.flush()
    return sw.toString()
} 

사용방법:

 Log.d("ERROR_STACKTRACE","${t.stackTraceToString()}") // 't' is the throwable obj

언급URL : https://stackoverflow.com/questions/7841232/java-android-how-to-print-out-a-full-stack-trace