W systemie Android (Java) jak wydrukować pełny ślad stosu? Jeśli moja aplikacja ulegnie awarii z powodu nullPointerException lub czegoś podobnego, wydrukuje (prawie) pełny ślad stosu, jak poniżej:
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
Jednak czasami do celów debugowania chcę rejestrować pełny ślad stosu z miejsca, w którym jestem w kodzie. Pomyślałem, że mogę to zrobić:
StackTraceElement trace = new Exception().getStackTrace();
Log.d("myapp", trace.toString());
Ale to tylko wypisuje wskaźnik do obiektu ... Czy muszę iterować przez wszystkie elementy śledzenia stosu, aby je wydrukować? A może istnieje prosta metoda, aby to wszystko wydrukować?
Odpowiedzi:
Istnieją zastąpienia wszystkich metod dziennika z
(String tag, String msg, Throwable tr)
podpisami.Przekazanie wyjątku jako trzeciego parametru powinno dać pełny ślad stosu w logcat.
źródło
getStackTraceString()
trzyargumentowe metody dziennika używają metody, o której wspomniał @Thomas za kulisami.Poniższe powinny załatwić sprawę:
Zauważ, że
...x more
na końcu nie odcina żadnych informacji ze śladu stosu:... lub innymi słowy, zamień
x more
na ostatniex
wiersze pierwszego wyjątku.źródło
getStackTraceString()
? Nie pojawia się w Eclipse? To nie jest częśćThrowable
aniException
...import android.util.Log;
).Użyj Log.getStackTraceString (Throwable t). Możesz uzyskać dłuższe ślady stosu, kopiąc głębiej. Na przykład:
Pobrano z http://developer.android.com/reference/android/util/Log.html#getStackTraceString%28java.lang.Throwable%29
źródło
Log.getStackTraceString()
nie rejestruje śladu stosu, po prostu zwraca go jako ciąg. Powyższy kod nie zarejestruje niczego, a także zakończy się niepowodzeniem z NPE, jeśli take.getCause()
jestnull
.źródło
Możesz użyć tego:
źródło
Możesz również wydrukować ślad stosu w dowolnym punkcie kodu aplikacji przy użyciu metod, takich jak
Thread.dumpStack()
Przejdź przez łącze, aby uzyskać więcej informacji
źródło
Musisz użyć Throwable Object, aby uzyskać pełny stackTrace.
Odniesienie: https://stackoverflow.com/a/18546861
źródło
Szybko wykonałem teraz funkcję rekurencyjną, która będzie iterować funkcje throwable i throwable.getCause ().
Dzieje się tak, ponieważ każda „throwable.getCause ()” zwraca do Ciebie nowy komunikat o wyjątku z kilkoma powtórzonymi wierszami i nowymi wierszami. Więc koncepcja jest taka: jeśli istnieje „przyczyna”, jest linia z „n więcej ..” na głównym rzucie, więc otrzymuję ostatnią linię przed tą z „n więcej ..”, wtedy otrzymuję komunikat o przyczynie i na koniec podłańcuch komunikatu o przyczynie, pobierając tylko część po ostatniej powtórzonej linii (ostatnia linia, która pojawia się w obu: główny rzut i przyczyna rzucana).
Następnie używam rekurencji, gdy otrzymuję komunikat o przyczynie, więc ponownie wywołując tę samą funkcję, aby uzyskać komunikat o przyczynie z głównego elementu rzutującego, otrzymam już zastąpiony komunikat. Jeśli przyczyna wyrzucenia z głównego miotanego ma również inną przyczynę, więc główny rzut ma 3 poziomy (główny -> przyczyna -> przyczyna-przyczyny), na głównym wyrzucanym rzucie otrzymam "komunikat o przyczynie" już zastąpiony komunikat (używając tej samej koncepcji pliku main
Próbowałem tylko z 2 poziomami (główna -> przyczyna) a nie z więcej: / Jeśli coś jest nie tak to edytuj funkcję i napisz komentarz: D
miłego kodowania i miłego dnia też: D
Ważny:
Ten kod czasami otrzymuje wyjątek, jeśli „st” nie zawiera „\ n” lub podobnego (znalazłem jakiś rodzaj wyjątków, w których stosowe ślady mają ten problem). Aby rozwiązać ten problem, musisz dodać czek przed wierszem kodu: „String r1 = ...”
Musisz sprawdzić: „st” zawiera „\ n” oraz czy indeksy początkowy i końcowy „st.subSequence” są prawidłowe.
W każdym razie proponuję umieścić to wewnątrz try-catch i zwrócić pusty ciąg w przypadku wyjątku. (Jest rekurencyjny, więc zwrócony pusty ciąg zostanie połączony z poprzednim przetworzonym ciągiem).
źródło