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ślaniu konkretnych wątków, które mogą być przyczyną problemów. Analizujemy błędy ANR, a potem na panelu Crashlytics otagowujemy odpowiednie wątki, aby wyświetlać wskazówki dotyczące ich debugowania.
W następnych sekcjach tej strony wyjaśniamy, co oznaczają poszczególne tagi błędów ANR, przedstawiamy przykładowy błąd ANR z takim tagiem oraz podajemy zalecane rozwiązanie umożliwiające debugowanie tego błędu.
Triggered ANR
Wątek, który był zablokowany zbyt długo i wywołał błąd ANR, jest oznaczony tagiem Triggered ANR
.
Problem może dotyczyć głównego wątku aplikacji lub dowolnego wątku, który nie odpowiada. Wątek otagowany jako Triggered ANR
może, ale nie musi być rzeczywistą przyczyną błędu ANR. Aby zapewnić informacje do debugowania i rozwiązywania tych błędów ANR,
Crashlyticstaguje 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ć w wątku.
Deadlocked
Wszystkie wątki, które zostały uznane za zaangażowane w blokadę wzajemną, która wywołała błąd ANR, są oznaczone tym tagiem Deadlocked
.
Blokada występuje, gdy wątek przechodzi w stan oczekiwania, ponieważ wymagany zasób jest zablokowany przez inny wątek, który również oczekuje na zasób zablokowany przez pierwszy wątek. Jeśli główny wątek aplikacji znajduje się w takiej sytuacji, prawdopodobnie będą się pojawiać błędy ANR.
Zobacz przykład
Oto 2 wątki, które uczestniczą 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 zaangażowane w błąd Deadlock i sprawdź zasoby/blokady uzyskane przez te wątki. Możliwe rozwiązania znajdziesz w artykule Deadlock (w języku angielskim) i Algorytmy zapobiegające blokowaniu się (w języku angielskim).
IO Root blocking
Każdy 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 też 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 jestIO Root blocking
, możesz też użyć trybu rygorystycznego, aby zidentyfikować niezamierzone operacje wejścia-wyjścia, które występują w wątku głównym.
Root blocking
Każdy wątek, który zablokował wątek otagowany jako
Triggered ANR
, jest opatrzony 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 jakieś wątki Triggered ANR
oczekiwały (być może pośrednio) na inne wątki, są one Root blocking
. Może być wiele przyczyn, dla których wątek jest główną przyczyną ANR.
Zobacz przykłady
Oto kilka przykładów dotyczących 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 obciążenie 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 tła.
Zminimalizuj intensywne operacje we/wy, takie jak wczytywanie z bazy danych, w wątku głównym.
Unknown root cause
Wątek jest otagowany tagiem Unknown root cause
, jeśli był to wątek, który wywołał błąd ANR, ale w momencie jego wystąpienia nie był aktywny. Crashlytics nie ma wystarczających informacji, aby określić główną przyczynę. Nie ma oczywistej przyczyny 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. Na przykład zidentyfikuj miejsca w kodzie, w których wątek główny aplikacji może być zajęty dłużej niż
5 sekund.