Les erreurs ANR (Application Not Responding) se déclenchent lorsque le thread UI de l'
application ne répond pas pendant plus de cinq secondes. Pour en savoir
plus sur les erreurs ANR et leur diagnostic, consultez la
documentation Android.
De plus, Crashlytics peut vous aider à identifier des threads problématiques spécifiques. Nous
analysons les erreurs ANR, puis, dans le
tableau de bord DevOps et engagement > Crashlytics, nous balisons
les threads applicables pour vous fournir des conseils sur la façon de déboguer l'erreur ANR.
Les sections suivantes de cette page expliquent la signification de chaque balise ANR, présentent un exemple d'erreur ANR avec cette balise et fournissent une solution recommandée pour déboguer l'erreur ANR.
Triggered ANR
Un thread bloqué trop longtemps et ayant déclenché l'erreur ANR est annoté avec
cette Triggered ANR balise.
Le thread problématique peut être le thread principal de l'application ou tout thread jugé non réactif. Toutefois, le thread balisé comme
Triggered ANR peut être ou non la cause réelle de
l'erreur ANR. Pour fournir des informations permettant de déboguer et de corriger ces erreurs ANR,
Crashlytics balise également tous les autres threads impliqués dans l'erreur ANR. Dans les sections suivantes de cette page, découvrez les autres balises qui peuvent être appliquées à un thread.
Deadlocked
Tous les threads impliqués dans un interblocage ayant entraîné l'erreur ANR sont
annotés avec la balise Deadlocked.
Un interblocage se produit lorsqu'un thread passe à l'état d'attente, car une ressource requise est détenue par un autre thread, qui attend également une ressource détenue par le premier thread. Si le thread principal de l'application se trouve dans cette situation, il est probable que des erreurs ANR se produisent.
Voir un exemple
Voici deux threads impliqués dans un interblocage :
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)
Recommandation
Examinez les threads impliqués dans l'interblocage et vérifiez les ressources/verrous acquis par ces threads. Pour connaître les solutions possibles, consultez
Interblocage et
algorithmes de prévention des interblocages.
IO Root blocking
Tout thread ayant exécuté des opérations d'E/S lentes et bloqué le
Triggered ANR thread est annoté avec la
IO Root blocking balise. Si le
Triggered ANR thread n'est pas bloqué par d'autres threads,
alors le IO Root blocking thread est également un
Root blocking thread.
Voir des exemples
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 )
Recommandation
En général, votre application ne doit pas exécuter d'opérations d'E/S coûteuses sur le thread principal. Si le thread principal est
IO Root blocking, vous pouvez également utiliser
le mode strict
pour identifier les opérations d'E/S involontaires qui se produisent sur le thread principal.
Root blocking
Tout thread ayant bloqué le thread balisé comme
Triggered ANR est annoté avec la balise
Root blocking. Si un thread porte les balises
Root blocking et
Triggered ANR, cela signifie qu'aucun autre thread ne
bloque ce thread.
Si des Triggered ANR threads attendaient (peut-être
de manière transitive) d'autres threads, ils sont
Root blocking. Un thread peut être à l'origine de l'erreur ANR pour différentes raisons.
Voir des exemples
Voici quelques exemples basés sur l'état du thread :
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 )
Recommandation
Réduisez le travail nécessitant une utilisation intensive du processeur dans le thread principal. Utilisez des threads de travail ou d'arrière-plan pour effectuer des tâches nécessitant une utilisation intensive du processeur.
Réduisez le travail nécessitant une utilisation intensive des E/S, comme le chargement à partir d'une base de données, sur le thread principal.
Unknown root cause
Un thread est balisé avec la balise Unknown root cause si
il s'agit du thread qui a déclenché l'erreur ANR, mais qu'il était inactif dans le processus lorsque l'
erreur ANR s'est produite. Crashlytics ne dispose pas de suffisamment d'informations pour déterminer
la cause première. Il n'y a aucune raison évidente pour laquelle cette erreur ANR s'est produite.
Voir un exemple
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 )
Recommandation
Suivez les conseils généraux sur la prévention des erreurs ANR. Par exemple, identifiez les
emplacements de votre code où le thread principal de l'application peut être occupé pendant plus de
cinq secondes.