Błędy typu Aplikacja nie odpowiada (ANR) są wywoływane, gdy wątek interfejsu aplikacji nie odpowiada przez ponad 5 sekund. Więcej informacji o błędach ANR i ich diagnozowaniu znajdziesz w dokumentacji Androida.
Crashlytics może też pomóc w określeniu konkretnych wątków, w których występuje problem. Analizujemy błędy ANR, a następnie w Crashlyticspanelu oznaczamy odpowiednie wątki, aby podać wskazówki dotyczące debugowania błędów ANR.
W kolejnych sekcjach na tej stronie znajdziesz wyjaśnienie znaczenia każdego tagu błędu ANR, przykładowy błąd ANR z tym tagiem oraz zalecane rozwiązanie do debugowania błędu ANR.
Triggered ANR
Wątek, który był zablokowany zbyt długo i wywołał błąd ANR, jest oznaczony tym tagiem: Triggered ANR
.
Problemowy wątek może być głównym wątkiem aplikacji lub dowolnym wątkiem, który nie odpowiada. Wątek oznaczony tagiem
Triggered ANR
może, ale nie musi być rzeczywistą przyczyną błędu ANR. Aby dostarczać informacji pomocnych w debugowaniu i rozwiązywaniu tych błędów ANR, Crashlyticsotagowuje też wszystkie inne wątki, które są z nimi powiązane. W kolejnych sekcjach tej strony dowiesz się więcej o innych tagach, które można zastosować do wątku.
Deadlocked
Wszystkie wątki, które uczestniczyły w zakleszczeniu, które wywołało błąd ANR, są oznaczone tagiem Deadlocked
.
Zakleszczenie występuje, gdy wątek przechodzi w stan oczekiwania, ponieważ wymagany zasób jest używany przez inny wątek, który również oczekuje na zasób używany przez pierwszy wątek. Jeśli w takiej sytuacji znajdzie się główny wątek aplikacji, prawdopodobnie wystąpią błędy ANR.
Zobacz przykład
Oto 2 wątki, które uczestniczyły w zakleszczeniu:
main (unknown): tid=1 systid=1568
com.android.server.pm.PackageManagerService$PackageManagerInternalImpl.getPackage(PackageManagerService.java:22701)
com.android.server.pm.PackageManagerService$PackageManagerInternalImpl.filterOnlySystemPackages(PackageManagerService.java:22787)
...
com.android.server.SystemServer.main(SystemServer.java:368)
java.lang.reflect.Method.invoke(Native method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:517)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
ActivityManager (unknown): tid=21 systid=1902
com.android.server.pm.PackageManagerService.getPackageSetting(PackageManagerService.java:23618)
com.android.server.pm.PackageManagerService.getPackageUid(PackageManagerService.java:4542)
...
android.os.Handler.handleCallback(Handler.java:907)
android.os.Handler.dispatchMessage(Handler.java:99)
android.os.Looper.loop(Looper.java:216)
android.os.HandlerThread.run(HandlerThread.java:67)
com.android.server.ServiceThread.run(ServiceThread.java:44)
Rekomendacja
Sprawdź wątki, które są objęte zakleszczeniem, i zasoby/blokady uzyskane przez te wątki. Możliwe rozwiązania znajdziesz w artykułach Zakleszczenie i Algorytmy zapobiegające zakleszczeniom.
IO Root blocking
Wątek, który wykonywał powolne operacje wejścia-wyjścia i zablokował wątek Triggered ANR
, jest oznaczony tagiem IO Root blocking
. Jeśli wątek Triggered ANR
nie jest blokowany przez inne wątki, to wątek IO Root blocking
jest także wątkiem Root blocking
.
Zobacz przykłady
Thread main(THREAD_STATE_TIMED_WAITING)
sun.misc.Unsafe.park( Unsafe.java:0 )
java.util.concurrent.locks.LockSupport.parkNanos( LockSupport.java:230 )
android.database.sqlite.SQLiteConnectionPool.waitForConnection( SQLiteConnectionPool.java:756 )
...
android.app.ActivityThread.main( ActivityThread.java:8192 )
Thread main(THREAD_STATE_NATIVE_WAITING)
Syscall
art::ConditionVariable::WaitHoldingLocks(art::Thread*)
art::GoToRunnable(art::Thread*)
art::JniMethodEnd(unsigned int, art::Thread*)
libcore.io.Linux.fdatasync( Linux.java:0 )
libcore.io.ForwardingOs.fdatasync( ForwardingOs.java:105 )
...
java.io.RandomAccessFile.write( RandomAccessFile.java:559 )
...
android.app.ActivityThread.main( ActivityThread.java:8192 )
Rekomendacja
Ogólnie rzecz biorąc, aplikacja nie powinna wykonywać kosztownych operacji wejścia-wyjścia w wątku głównym. Jeśli wątek główny jest IO Root blocking
, możesz też użyć trybu ścisłego, aby zidentyfikować niezamierzone operacje wejścia-wyjścia wykonywane w wątku głównym.
Root blocking
Wątek, który zablokował wątek otagowany jako
Triggered ANR
, jest oznaczony tagiem
Root blocking
. Jeśli wątek jest otagowany jednocześnie jako Root blocking
i Triggered ANR
, to nie ma innych wątków, które blokują ten wątek.
Jeśli jakiekolwiek wątki Triggered ANR
oczekiwały (być może pośrednio) na inne wątki, są one Root blocking
. Przyczyny, dla których wątek jest główną przyczyną błędu ANR, mogą być różne.
Zobacz przykłady
Oto kilka przykładów w zależności od stanu wątku:
Thread main(THREAD_STATE_RUNNABLE)
android.os.Parcel.createTypedArray( Parcel.java:3086 )
android.content.pm.PackageInfo.<init>( PackageInfo.java:546 )
...
android.app.ActivityThread$H.handleMessage( ActivityThread.java:2166 )
android.os.Handler.dispatchMessage( Handler.java:106 )
android.os.Looper.loop( Looper.java:246 )
android.app.ActivityThread.main( ActivityThread.java:8633 )
Thread main(THREAD_STATE_BLOCKED)
DBHelper.runOnDB( DBHelper.java:97 )
DBHelper.runDb( DBHelper.java:125 )
...
java.lang.reflect.Method.invoke( Method.java:0 )
EventBus.invokeSubscriber( EventBus.java:510 )
postToSubscription( EventBus.java:437 )
...
android.os.Handler.handleCallback( Handler.java:938 )
android.os.Handler.dispatchMessage( Handler.java:99 )
android.os.Looper.loop( Looper.java:268 )
android.app.ActivityThread.main( ActivityThread.java:7904 )
Rekomendacja
Zminimalizuj pracę wymagającą dużej mocy obliczeniowej procesora w wątku głównym. Do wykonywania zadań wymagających dużej mocy obliczeniowej procesora używaj wątków roboczych lub wątków działających w tle.
Zminimalizuj w wątku głównym operacje wymagające dużej liczby operacji wejścia/wyjścia, takie jak wczytywanie danych z bazy danych.
Unknown root cause
Wątek jest oznaczony tagiem Unknown root cause
, jeśli wywołał błąd ANR, ale w momencie jego wystąpienia był nieaktywny. Crashlytics nie ma wystarczających informacji, aby określić główną przyczynę. Nie ma oczywistego powodu wystąpienia tego błędu ANR.
Zobacz przykład
Thread main(THREAD_STATE_NATIVE_WAITING) __epoll_pwait
android::Looper::pollInner(int)
android::Looper::pollOnce(int, int*, int*, void**)
android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)
android.os.MessageQueue.nativePollOnce( MessageQueue.java:0 )
android.os.MessageQueue.next( MessageQueue.java:335 )
android.os.Looper.loop( Looper.java:193 )
android.app.ActivityThread.main( ActivityThread.java:8019 )
Rekomendacja
Postępuj zgodnie z ogólnymi wskazówkami dotyczącymi zapobiegania błędom ANR. Możesz na przykład zidentyfikować miejsca w kodzie, w których wątek główny aplikacji może być zajęty przez ponad 5 sekund.