Nicht reagierenden Thread suchen

In diesem Dokument wird gezeigt, wie Sie den nicht reagierenden Thread in einem ANR-Stack identifizieren. Dump. Der nicht reagierende Thread variiert je nach Art des ANR-Fehlers, wie unten dargestellt .

ANR-Typ Thread reagiert nicht
Eingabeweiterleitung Hauptthread
Eingabeweiterleitung – kein fokussiertes Fenster Hauptthread Diese Art von ANR-Fehler wird normalerweise nicht durch eine blockierte Diskussions-Thread.
Übertragungsempfänger (synchron) Thread wird ausgeführt onReceive() Dies ist der Hauptthread, es sei denn, ein benutzerdefinierter Handler für einen Nicht-Hauptthread angegeben mit Context.registerReceiver
Übertragungsempfänger (asynchron) Überprüfen Sie den Code, um zu sehen, welcher Thread oder welcher Thread-Pool die Übertragung nach der Veröffentlichung goAsync aufgerufen wird.
Zeitlimit für Dienstausführung Hauptthread
Start des Dienstes im Vordergrund Hauptthread
Contentanbieter reagiert nicht Dazu haben Sie zwei Möglichkeiten: <ph type="x-smartling-placeholder">
    </ph>
  • Binder-Thread, wenn ANR durch einen langsamen Contentanbieter verursacht wird Abfrage.
  • Hauptthread, wenn der ANR-Fehler durch einen langen App-Start verursacht wird.
Keine Antwort auf onStartJob oder onStopJob Hauptthread

Manchmal reagiert der Thread aufgrund einer Ursache in einem anderen Thread nicht oder Prozess zu verstehen. Der Thread reagiert möglicherweise nicht, weil auf Folgendes gewartet wird:

  • Eine Sperre, die von einem anderen Thread gehalten wird.
  • Ein langsamer Binder ruft einen anderen Prozess auf.

Häufige Ursachen für nicht reagierende Threads

Wenn Threads nicht reagieren, kann dies folgende Ursachen haben:

Langsamer Binder-Aufruf

Obwohl die meisten Binder-Aufrufe schnell sind, kann das lange Ende sehr langsam sein. Dies ist häufiger, wenn das Gerät geladen oder der Binder-Antwort-Thread langsam, z. B. durch Schlosskonflikt, viele eingehende Binder-Anrufe oder Hardware HAL-Zeitlimit (Abstraktionsschicht).

Sie können dies lösen, indem Sie synchrone Binder-Aufrufe in Hintergrundthreads verschieben. wenn möglich. Wenn der Anruf im Hauptthread erfolgen muss, finden Sie heraus, warum der Anruf ist langsam. Dazu verwenden Sie am besten Perfetto-Traces.

Suchen Sie in den Stacks nach BinderProxy.transactNative oder Binderproxy.transact. Dies bedeutet, dass ein Binder-Aufruf stattfindet. Diesen beiden Zeilen folgen Sie, die aufgerufene binder API. Im folgenden Beispiel soll der Aufruf IAccessibilityManager.addClient

main tid=123

...
android.os.BinderProxy.transactNative (Native method)
android.os.BinderProxy.transact (BinderProxy.java:568)
android.view.accessibility.IAccessibilityManager$Stub$Proxy.addClient (IAccessibilityManager.java:599)
...

Viele aufeinanderfolgende Binder-Aufrufe

Wenn Sie viele aufeinanderfolgende Binder-Aufrufe in einer engen Schleife durchführen, kann ein Thread über einen längeren Zeitraum.

Eine blockierende E/A

Führen Sie niemals eine blockierende E/A im Hauptthread durch. Dies ist ein Anti-Pattern.

Konflikt durch Sperre

Wenn ein Thread beim Erhalt einer Sperre blockiert wird, kann dies zu einem ANR-Fehler führen.

Das folgende Beispiel zeigt, dass der Hauptthread blockiert wird, wenn versucht wird, einen Schloss:

main (tid=1) Blocked

Waiting for com.example.android.apps.foo.BarCache (0x07d657b7) held by
ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD
[...]
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:5412)
[...]

Der blockierende Thread sendet eine HTTP-Anfrage zum Herunterladen eines Videos:

ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD (tid=110) Waiting

at jdk.internal.misc.Unsafe.park(Native method:0)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:715)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1047)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:230)
at com.example.android.apps.foo.HttpRequest.execute(HttpRequest:136)
at com.example.android.apps.foo$Task$VideoLoadTask.downloadVideoToFile(RequestExecutor:711)
[...]

Teurer Frame

Wenn Sie zu viele Dinge in einem einzelnen Frame rendern, kann dies dazu führen, dass der Hauptthread nicht reagieren, wie z. B.:

  • Viele unnötige Elemente werden gerendert, die nicht auf dem Bildschirm zu sehen sind.
  • Verwendung eines ineffizienten Algorithmus wie O(n^2) beim Rendern vieler UI-Elemente Elemente.

Durch andere Komponente blockiert

Wenn eine andere Komponente, z. B. ein Übertragungsempfänger, den Hauptthread länger als fünf Sekunden dauern, kann dies zu ANR-Fehlern beim Senden von Eingaben und zu schwerwiegenden Verzögerungen führen.

Vermeiden Sie umfangreiche Arbeiten am Hauptthread in App-Komponenten. Broadcast ausführen an einen anderen Thread senden.