Existe-t-il un moyen de savoir où mon application a lancé un ANR (Application Not Responding). J'ai jeté un œil au fichier traces.txt dans / data et je vois une trace pour mon application. C'est ce que je vois dans la trace.
DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
| group="main" sCount=1 dsCount=0 s=0 obj=0x400143a8
| sysTid=691 nice=0 sched=0/0 handle=-1091117924
at java.lang.Object.wait(Native Method)
- waiting on <0x1cd570> (a android.os.MessageQueue)
at java.lang.Object.wait(Object.java:195)
at android.os.MessageQueue.next(MessageQueue.java:144)
at android.os.Looper.loop(Looper.java:110)
at android.app.ActivityThread.main(ActivityThread.java:3742)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
at dalvik.system.NativeStart.main(Native Method)
"Binder Thread #3" prio=5 tid=15 NATIVE
| group="main" sCount=1 dsCount=0 s=0 obj=0x434e7758
| sysTid=734 nice=0 sched=0/0 handle=1733632
at dalvik.system.NativeStart.run(Native Method)
"Binder Thread #2" prio=5 tid=13 NATIVE
| group="main" sCount=1 dsCount=0 s=0 obj=0x433af808
| sysTid=696 nice=0 sched=0/0 handle=1369840
at dalvik.system.NativeStart.run(Native Method)
"Binder Thread #1" prio=5 tid=11 NATIVE
| group="main" sCount=1 dsCount=0 s=0 obj=0x433aca10
| sysTid=695 nice=0 sched=0/0 handle=1367448
at dalvik.system.NativeStart.run(Native Method)
"JDWP" daemon prio=5 tid=9 VMWAIT
| group="system" sCount=1 dsCount=0 s=0 obj=0x433ac2a0
| sysTid=694 nice=0 sched=0/0 handle=1367136
at dalvik.system.NativeStart.run(Native Method)
"Signal Catcher" daemon prio=5 tid=7 RUNNABLE
| group="system" sCount=0 dsCount=0 s=0 obj=0x433ac1e8
| sysTid=693 nice=0 sched=0/0 handle=1366712
at dalvik.system.NativeStart.run(Native Method)
"HeapWorker" daemon prio=5 tid=5 VMWAIT
| group="system" sCount=1 dsCount=0 s=0 obj=0x4253ef88
| sysTid=692 nice=0 sched=0/0 handle=1366472
at dalvik.system.NativeStart.run(Native Method)
----- end 691 -----
Comment puis-je savoir où se situe le problème? Les méthodes de la trace sont toutes des méthodes SDK.
Merci.
android.os.MessageQueue.nativePollOnce(Native Method)
. Puis-je l'ignorer en toute sécurité?Réponses:
Un ANR se produit lorsqu'une opération longue a lieu dans le thread "principal". Il s'agit du thread de la boucle d'événements, et s'il est occupé, Android ne peut pas traiter d'autres événements GUI dans l'application, et lance ainsi une boîte de dialogue ANR.
Maintenant, dans la trace que vous avez postée, le fil principal semble bien fonctionner, il n'y a pas de problème. Il est inactif dans MessageQueue, en attente d'un autre message. Dans votre cas, l'ANR était probablement une opération plus longue, plutôt que quelque chose qui bloquait le thread de manière permanente, donc le thread d'événement a récupéré une fois l'opération terminée et votre trace est passée après l'ANR.
Détecter où les ANR se produisent est facile s'il s'agit d'un blocage permanent (blocage de l'acquisition de certains verrous par exemple), mais plus difficile s'il ne s'agit que d'un retard temporaire. Tout d'abord, passez en revue votre code et recherchez les points vulnérables et les opérations de longue durée. Les exemples peuvent inclure l'utilisation de sockets, de verrous, de sommeil de thread et d'autres opérations de blocage à partir du thread d'événement. Vous devez vous assurer que tout cela se produit dans des threads séparés. Si rien ne semble être le problème, utilisez DDMS et activez la vue des threads. Cela montre tous les threads de votre application similaires à la trace que vous avez. Reproduisez l'ANR et actualisez le thread principal en même temps. Cela devrait vous montrer précisément ce qui se passe au moment de l'ANR
la source
Vous pouvez activer StrictMode dans l'API niveau 9 et supérieur.
la source
Vous vous demandez quelle tâche contient un thread d'interface utilisateur. Le fichier de trace vous donne un indice pour trouver la tâche. vous devez enquêter sur un état de chaque thread
État du fil
Focus sur l'état SUSPENDU, MONITOR. L'état du moniteur indique quel thread est étudié et l'état SUSPENDED du thread est probablement la principale raison du blocage.
Étapes d'enquête de base
trace ne contient pas toujours "en attente de verrouillage". dans ce cas, il est difficile de trouver la raison principale.
la source
- waiting to lock an unknown object
intérieur"HeapTaskDaemon" daemon prio=5 tid=8 Blocked
. Qu'est-ce que cela signifie que quelqu'un peut aider?J'apprends Android depuis quelques mois, donc je suis loin d'être un expert, mais j'ai été vraiment déçu par la documentation sur les ANR.
La plupart des conseils semblent viser à les éviter ou à les corriger en regardant aveuglément votre code, ce qui est génial, mais je n'ai rien trouvé en analysant la trace.
Il y a trois choses que vous devez vraiment rechercher avec les journaux ANR.
1) Deadlocks: Lorsqu'un thread est dans l'état WAIT, vous pouvez regarder à travers les détails pour trouver qui il est "holdby =". La plupart du temps, il sera tenu seul, mais s'il est tenu par un autre fil, c'est probablement un signe de danger. Allez regarder ce fil et voyez ce qu'il contient. Vous pourriez trouver une boucle, ce qui indique clairement que quelque chose ne va pas. C'est assez rare, mais c'est le premier point car quand ça arrive, c'est un cauchemar
2) Fil principal en attente: Si votre fil principal est dans l'état WAIT, vérifiez s'il est détenu par un autre fil. Cela ne devrait pas se produire, car votre thread d'interface utilisateur ne doit pas être détenu par un thread d'arrière-plan.
Ces deux scénarios signifient que vous devez retravailler votre code de manière significative.
3) Opérations lourdes sur le thread principal: C'est la cause la plus courante des ANR, mais parfois l'une des plus difficiles à trouver et à corriger. Regardez les principaux détails du fil. Faites défiler la trace de la pile et jusqu'à ce que vous voyiez les classes que vous reconnaissez (à partir de votre application). Regardez les méthodes de la trace et déterminez si vous effectuez des appels réseau, des appels db, etc. à ces endroits.
Enfin, et je m'excuse d'avoir branché sans vergogne mon propre code, vous pouvez utiliser l'analyseur de journaux python que j'ai écrit à https://github.com/HarshEvilGeek/Android-Log-Analyzer Cela passera par vos fichiers journaux, ouvrez les fichiers ANR, trouvez les blocages, trouvez les threads principaux en attente, trouvez les exceptions non interceptées dans vos journaux d'agent et imprimez le tout à l'écran d'une manière relativement facile à lire. Lisez le fichier ReadMe (que je suis sur le point d'ajouter) pour savoir comment l'utiliser. Cela m'a beaucoup aidé la semaine dernière!
la source
Chaque fois que vous analysez des problèmes de synchronisation, le débogage n'aide souvent pas, car le gel de l'application à un point d'arrêt éliminera le problème.
Votre meilleur pari est d'insérer beaucoup d'appels de journalisation (Log.XXX ()) dans les différents threads et rappels de l'application et de voir où se situe le retard. Si vous avez besoin d'un stacktrace, créez une nouvelle exception (instanciez-en une) et enregistrez-la.
la source
Qu'est-ce qui déclenche l'ANR?
En général, le système affiche un ANR si une application ne peut pas répondre à l'entrée utilisateur.
Dans toute situation dans laquelle votre application effectue une opération potentiellement longue, vous ne devez pas effectuer le travail sur le thread d'interface utilisateur, mais plutôt créer un thread de travail et y effectuer la majeure partie du travail. Cela maintient le thread d'interface utilisateur (qui pilote la boucle d'événements de l'interface utilisateur) en cours d'exécution et empêche le système de conclure que votre code est gelé.
Comment éviter les ANR
Les applications Android fonctionnent normalement entièrement sur un seul thread (par défaut le "thread UI" ou "thread principal"). Cela signifie que tout ce que votre application fait dans le thread d'interface utilisateur qui prend beaucoup de temps peut déclencher la boîte de dialogue ANR car votre application ne se donne pas la possibilité de gérer l'événement d'entrée ou les diffusions d'intention.
Par conséquent, toute méthode qui s'exécute dans le thread d'interface utilisateur doit effectuer le moins de travail possible sur ce thread. En particulier, les activités doivent faire le moins possible pour mettre en place des méthodes clés du cycle de vie telles que onCreate () et onResume (). Les opérations potentiellement longues, telles que les opérations de réseau ou de base de données, ou les calculs coûteux en calcul comme le redimensionnement des bitmaps doivent être effectués dans un thread de travail (ou dans le cas d'opérations de bases de données, via une requête asynchrone).
Code: thread de travail avec la classe AsyncTask
Code: Exécuter le thread de travail
Pour exécuter ce thread de travail, créez simplement une instance et appelez execute ():
La source
http://developer.android.com/training/articles/perf-anr.html
la source
mon problème avec ANR, après beaucoup de travail, j'ai découvert qu'un fil appelait une ressource qui n'existait pas dans la mise en page, au lieu de renvoyer une exception, j'ai eu ANR ...
la source
Vous devez rechercher «en attente de verrouillage» dans le fichier /data/anr/traces.txt
pour plus de détails: Ingénieur pour hautes performances avec des outils d'Android & Play (Google I / O '17)
la source
Basique sur la réponse @Horyun Lee, j'ai écrit un petit script python pour aider à enquêter sur ANR à partir de
traces.txt
.Les ANR seront affichés sous forme de graphiques
graphviz
si vous les avez installésgrapvhviz
sur votre système.Un png sera affiché comme ci-dessous s'il y a des ANR détectés dans le fichier
traces.txt
. C'est plus intuitif.Le
traces.txt
fichier d' exemple utilisé ci-dessus a été obtenu à partir d' ici .la source
Envisagez d'utiliser la bibliothèque ANR-Watchdog pour suivre et capturer avec précision les traces de pile ANR avec un niveau de détail élevé. Vous pouvez ensuite les envoyer à votre bibliothèque de rapports de plantage. Je recommande d'utiliser
setReportMainThreadOnly()
dans ce scénario. Vous pouvez soit faire en sorte que l'application lève une exception non fatale du point de gel, soit forcer l'application à se fermer lorsque l'ANR se produit.Notez que les rapports ANR standard envoyés à votre console développeur Google Play ne sont souvent pas suffisamment précis pour identifier le problème exact. C'est pourquoi une bibliothèque tierce est nécessaire.
la source