Java / Android - Як роздрукувати повний слід стека?


124

Як в Android (Java) можна роздрукувати повний слід стека? Якщо мій додаток виходить з ладу nullPointerException або щось подібне, воно виводить (майже) повний слід стека так:

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

Але це просто виводить покажчик на об’єкт ... Чи потрібно мені повторювати всі мікроелементи стека, щоб надрукувати їх? Або існує простий метод роздрукувати все це?


1
Ви можете використовувати цей метод Thread.currentThread () getStackTrace (). Stackoverflow.com/questions/1069066 / ...
user2024270

Відповіді:


119

Існує переоцінка всіх методів журналу з (String tag, String msg, Throwable tr)підписами.

Якщо пройти виняток як третій параметр, ви повинні отримати повний стек траксів у logcat.


5
FYI getStackTraceString()триаргументаційні методи журналу використовують метод, згаданий @Thomas за кадром.
Philipp Reichart

6
Я розробляв Android протягом двох років і ніколи цього не помічав. Велике спасибі.
Анх Туан

Дивлячись на вихідний код, ви маєте рацію @PhilippReichart. Ось код для Log.d на AOSP 4.2.2_r1
Ehtesh Choudhury

152

Слід виконати трюк:

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

Зверніть увагу, що ...x moreнаприкінці не відрізається жодна інформація із сліду стека:

(Це вказує), що залишок сліду стека для цього винятку відповідає вказаній кількості кадрів у нижній частині сліду стека за винятком, який був викликаний цим винятком (виняток "огороджувальний").

... або іншими словами, замініть x moreостанніми xрядками з першого винятку.


1
Звідки getStackTraceString()? Не відображається в Eclipse? Це не частина Throwableабо Exception....
Джейк Вілсон

9
"... ще 6" наприкінці не зрізає жодної інформації. Це говорить вам про те, що решта сліду стека така ж, як і для верхнього винятку. Подивіться останні 6 рядків з першого винятку.
Томаш

Можливо, вам потрібно буде імпортувати бібліотеку журналів (використовуючи import android.util.Log;).
Dan

10

Використовуйте 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


Log.getStackTraceString()не записує слід стека, він просто повертає його як String. Вищевказаний код нічого не запише, а також вийде з ладу з NPE, якщо e.getCause()є null.
Philipp Reichart

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

6

Ви можете скористатися цим:

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


2

Щоб отримати повний 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


0

Я швидко зробив тепер рекурсивну функцію, яка дозволить повторити перекидний і кинутий.getCause ().

Це тому, що кожен "bacable.getCause ()" повертає вам нове повідомлення про виняток із деякими повторними рядками та новими рядками. Таким чином, концепція така: якщо є "причина", є рядок з "більше n .." на головній передачі, тому я отримую останній рядок перед тим, з "п більше ..", то я отримую повідомлення про причину і нарешті, я підстроковуючи повідомлення про причину, отримуючи лише частину після останнього повтореного рядка (останній рядок, який з’являється в обох: основний, що підлягає передачі та перекидається причина).

Тоді я використовую рекурсію, коли отримую повідомлення про причину, тому повторно викликаю ту саму функцію, щоб отримати повідомлення про причину від основної передачі, я отримаю вже замінене повідомлення. Якщо причина, яка може бути передана з основної переданої частини, має ще одну причину, тож основна передача має 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" або подібного (я виявив, що у певних стекань винятків є ця проблема). Для вирішення цього питання потрібно додати рядки перед рядком коду: "Рядок r1 = ..."

Вам потрібно перевірити: "st" містить "\ n" та чи є початкові та кінцеві індекси "st.subSequence" дійсними.

У будь-якому разі, я пропоную вкласти це всередині спробувати-улов і повернути порожній рядок у випадку винятку. (Це рекурсивно, тому повернута порожня рядок буде об'єднана в попередню оброблювану рядок).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.