Gibt es eine Möglichkeit herauszufinden, wo meine App eine ANR (Application Not Responding) ausgelöst hat? Ich habe mir die Datei traces.txt in / data angesehen und sehe eine Ablaufverfolgung für meine Anwendung. Das sehe ich in der Spur.
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 -----
Wie kann ich herausfinden, wo das Problem liegt? Die Methoden im Trace sind alle SDK-Methoden.
Vielen Dank.
android
performance
android-anr-dialog
lostInTransit
quelle
quelle
android.os.MessageQueue.nativePollOnce(Native Method)
. Kann ich es ignorieren?Antworten:
Eine ANR tritt auf, wenn eine lange Operation im "Haupt" -Thread stattfindet. Dies ist der Ereignisschleifenthread. Wenn er ausgelastet ist, kann Android keine weiteren GUI-Ereignisse in der Anwendung verarbeiten und löst daher einen ANR-Dialog aus.
In der von Ihnen geposteten Ablaufverfolgung scheint der Hauptthread in Ordnung zu sein, es gibt kein Problem. Es befindet sich in der MessageQueue im Leerlauf und wartet darauf, dass eine weitere Nachricht eingeht. In Ihrem Fall war die ANR wahrscheinlich eine längere Operation und nicht etwas, das den Thread dauerhaft blockiert hat, sodass der Ereignisthread nach Abschluss der Operation wiederhergestellt wurde und Ihre Ablaufverfolgung durchlaufen wurde nach dem ANR.
Das Erkennen, wo ANRs auftreten, ist einfach, wenn es sich um einen permanenten Block handelt (z. B. Deadlock beim Erwerb einiger Sperren), aber schwieriger, wenn es sich nur um eine vorübergehende Verzögerung handelt. Gehen Sie zunächst Ihren Code durch und suchen Sie nach gefährdeten Stellen und langfristigen Vorgängen. Beispiele können die Verwendung von Sockets, Sperren, Thread-Ruhezuständen und anderen Blockierungsvorgängen innerhalb des Ereignisthreads umfassen. Sie sollten sicherstellen, dass dies alles in separaten Threads geschieht. Wenn nichts das Problem zu sein scheint, verwenden Sie DDMS und aktivieren Sie die Thread-Ansicht. Hier werden alle Threads in Ihrer Anwendung angezeigt, die der von Ihnen verwendeten Ablaufverfolgung ähneln. Reproduzieren Sie die ANR und aktualisieren Sie gleichzeitig den Haupt-Thread. Das sollte Ihnen genau zeigen, was zum Zeitpunkt der ANR los ist
quelle
Sie können StrictMode in API-Level 9 und höher aktivieren .
quelle
Sie fragen sich, welche Aufgabe einen UI-Thread enthält. Die Trace-Datei gibt Ihnen einen Hinweis, um die Aufgabe zu finden. Sie müssen den Status jedes Threads untersuchen
Zustand des Fadens
Konzentrieren Sie sich auf den Status SUSPENDED, MONITOR. Der Überwachungsstatus gibt an, welcher Thread untersucht wird, und der SUSPENDED-Status des Threads ist wahrscheinlich der Hauptgrund für einen Deadlock.
Grundlegende Untersuchungsschritte
Trace enthält nicht immer "Warten auf Sperre". In diesem Fall ist es schwierig, den Hauptgrund zu finden.
quelle
- waiting to lock an unknown object
drinnen"HeapTaskDaemon" daemon prio=5 tid=8 Blocked
. Was bedeutet es, kann jemand helfen?Ich habe in den letzten Monaten Android gelernt, bin also weit entfernt von einem Experten, aber ich war wirklich enttäuscht von der Dokumentation zu ANRs.
Die meisten Ratschläge scheinen darauf ausgerichtet zu sein, sie zu vermeiden oder zu beheben, indem Sie blind durch Ihren Code schauen. Das ist großartig, aber ich konnte bei der Analyse der Spur nichts finden.
Es gibt drei Dinge, auf die Sie bei ANR-Protokollen wirklich achten müssen.
1) Deadlocks: Wenn sich ein Thread im Status WAIT befindet, können Sie die Details durchsehen, um herauszufinden, wer "holdby =" ist. Meistens wird es von selbst gehalten, aber wenn es von einem anderen Thread gehalten wird, ist dies wahrscheinlich ein Gefahrenzeichen. Schauen Sie sich diesen Thread an und sehen Sie, was er enthält. Möglicherweise finden Sie eine Schleife, was ein klares Zeichen dafür ist, dass etwas schief gelaufen ist. Dies ist ziemlich selten, aber es ist der erste Punkt, denn wenn es passiert, ist es ein Albtraum
2) Warten auf Hauptthread: Wenn sich Ihr Hauptthread im Status WAIT befindet, überprüfen Sie, ob er von einem anderen Thread gehalten wird. Dies sollte nicht passieren, da Ihr UI-Thread nicht von einem Hintergrund-Thread gehalten werden sollte.
In beiden Fällen müssen Sie Ihren Code erheblich überarbeiten.
3) Schwere Operationen am Haupt-Thread: Dies ist die häufigste Ursache für ANRs, aber manchmal eine der schwieriger zu findenden und zu behebenden. Schauen Sie sich die Details des Haupt-Threads an. Scrollen Sie im Stack-Trace nach unten und bis Sie Klassen sehen, die Sie erkennen (aus Ihrer App). Sehen Sie sich die Methoden in der Ablaufverfolgung an und finden Sie heraus, ob Sie an diesen Stellen Netzwerkanrufe, Datenbankanrufe usw. tätigen.
Schließlich, und ich entschuldige mich dafür, dass ich meinen eigenen Code schamlos eingesteckt habe, können Sie den Python-Protokollanalysator verwenden, den ich unter https://github.com/HarshEvilGeek/Android-Log-Analyzer geschrieben habe. Dieser wird Ihre Protokolldateien durchsuchen, ANR-Dateien öffnen und finden Deadlocks, wartende Haupt-Threads finden, nicht erfasste Ausnahmen in Ihren Agentenprotokollen finden und alles auf relativ einfach zu lesende Weise auf dem Bildschirm ausdrucken. Lesen Sie die ReadMe-Datei (die ich hinzufügen möchte), um zu erfahren, wie Sie sie verwenden. Es hat mir in der letzten Woche eine Menge geholfen!
quelle
Wenn Sie Zeitprobleme analysieren, hilft das Debuggen oft nicht, da das Problem durch Einfrieren der App an einem Haltepunkt behoben wird.
Am besten fügen Sie viele Protokollierungsanrufe (Log.XXX ()) in die verschiedenen Threads und Rückrufe der App ein und sehen, wo die Verzögerung liegt. Wenn Sie eine Stapelverfolgung benötigen, erstellen Sie eine neue Ausnahme (instanziieren Sie einfach eine) und protokollieren Sie sie.
quelle
Was löst ANR aus?
Im Allgemeinen zeigt das System eine ANR an, wenn eine Anwendung nicht auf Benutzereingaben reagieren kann.
In jeder Situation, in der Ihre App einen möglicherweise langwierigen Vorgang ausführt, sollten Sie die Arbeit nicht am UI-Thread ausführen, sondern stattdessen einen Arbeitsthread erstellen und den größten Teil der Arbeit dort ausführen. Dies hält den UI-Thread (der die Ereignisschleife der Benutzeroberfläche steuert) am Laufen und verhindert, dass das System zu dem Schluss kommt, dass Ihr Code eingefroren ist.
So vermeiden Sie ANRs
Android-Anwendungen werden normalerweise vollständig auf einem einzelnen Thread ausgeführt (standardmäßig "UI-Thread" oder "Haupt-Thread"). Dies bedeutet, dass alles, was Ihre Anwendung im UI-Thread tut, was lange dauert, den ANR-Dialog auslösen kann, da Ihre Anwendung sich selbst keine Chance gibt, das Eingabeereignis oder Absichtsübertragungen zu verarbeiten.
Daher sollte jede Methode, die im UI-Thread ausgeführt wird, so wenig Arbeit wie möglich an diesem Thread leisten. Insbesondere sollten Aktivitäten so wenig wie möglich dazu beitragen, wichtige Lebenszyklusmethoden wie onCreate () und onResume () einzurichten. Potenziell lange laufende Vorgänge wie Netzwerk- oder Datenbankvorgänge oder rechenintensive Berechnungen wie das Ändern der Größe von Bitmaps sollten in einem Arbeitsthread (oder im Fall von Datenbankvorgängen über eine asynchrone Anforderung) durchgeführt werden.
Code: Worker-Thread mit der AsyncTask-Klasse
Code: Worker-Thread ausführen
Um diesen Arbeitsthread auszuführen, erstellen Sie einfach eine Instanz und rufen Sie execute () auf:
Quelle
http://developer.android.com/training/articles/perf-anr.html
quelle
Mein Problem mit ANR, nach viel Arbeit fand ich heraus, dass ein Thread eine Ressource aufrief, die nicht im Layout vorhanden war, anstatt eine Ausnahme zurückzugeben, bekam ich ANR ...
quelle
Sie müssen in der Datei /data/anr/traces.txt nach "Warten auf Sperren" suchen
Weitere Informationen: Ingenieur für hohe Leistung mit Tools von Android & Play (Google I / O '17)
quelle
Grundlegend für die Antwort von @Horyun Lee habe ich ein kleines Python- Skript geschrieben , um die ANR von zu untersuchen
traces.txt
.Die ANRs werden als Grafiken ausgegeben,
graphviz
wenn Sie siegrapvhviz
auf Ihrem System installiert haben .Ein PNG wird wie unten ausgegeben, wenn in der Datei ANRs erkannt werden
traces.txt
. Es ist intuitiver.Die
traces.txt
oben verwendete Beispieldatei wurde von hier abgerufen .quelle
Erwägen Sie die Verwendung der ANR-Watchdog- Bibliothek, um ANR-Stapelspuren mit hoher Detailgenauigkeit genau zu verfolgen und zu erfassen. Sie können sie dann an Ihre Crash-Reporting-Bibliothek senden. Ich empfehle die Verwendung
setReportMainThreadOnly()
in diesem Szenario zu verwenden. Sie können entweder festlegen, dass die App eine nicht schwerwiegende Ausnahme vom Einfrierpunkt auslöst, oder die App erzwingen, wenn die ANR auftritt.Beachten Sie, dass die an Ihre Google Play Developer-Konsole gesendeten Standard-ANR-Berichte häufig nicht genau genug sind, um das genaue Problem zu ermitteln. Aus diesem Grund wird eine Bibliothek eines Drittanbieters benötigt.
quelle