In diesem Dokument wird gezeigt, wie Sie den nicht reagierenden Thread in einem ANR-Stack-Dump identifizieren. Der nicht reagierende Thread variiert je nach ANR-Typ, wie in der folgenden Tabelle gezeigt.
ANR-Typ | Thread reagiert nicht |
---|---|
Eingabeweiterleitung | Hauptthread |
Eingabeweiterleitung, kein fokussiertes Fenster | Hauptthread. Diese Art von ANR-Fehler wird normalerweise nicht durch blockierte Threads verursacht. |
Broadcast-Empfänger (synchron) | Thread wird ausgeführt: onReceive() .
Dies ist der Hauptthread, sofern kein benutzerdefinierter Handler für einen Nicht-Hauptthread mit Context.registerReceiver angegeben wird. |
Broadcast-Receiver (asynchron) | Prüfen Sie den Code, um festzustellen, welcher Thread oder Thread-Pool für die Verarbeitung des Broadcasts verantwortlich ist, nachdem goAsync aufgerufen wurde. |
Zeitlimit für Dienst wird ausgeführt | Hauptthread |
Dienst im Vordergrund starten | Hauptthread |
Contentanbieter antwortet nicht | Sie haben folgende Möglichkeiten:
|
Keine Antwort auf
onStartJob
oder
onStopJob |
Hauptthread |
Manchmal reagiert der Thread aufgrund einer Ursache in einem anderen Thread oder Prozess nicht. Der Thread reagiert möglicherweise nicht, weil auf Folgendes gewartet wurde:
- Eine Sperre für einen anderen Thread.
- Ein langsamer Binder-Aufruf an einen anderen Prozess.
Häufige Ursachen für nicht reagierende Threads
Häufige Ursachen für nicht reagierende Threads:
Langsamer Binder-Aufruf
Obwohl die meisten Binder-Aufrufe schnell sind, kann der Longtail sehr langsam sein. Dies ist wahrscheinlicher, wenn das Gerät geladen wird oder der Binder-Antwort-Thread langsam ist, z. B. aufgrund von Sperrenkonflikten, vielen eingehenden Binder-Aufrufen oder einem Zeitlimit für die Hardwareabstraction Layer (HAL).
Sie können dies lösen, indem Sie nach Möglichkeit synchrone Binder-Aufrufe in Hintergrundthreads verschieben. Wenn der Aufruf im Hauptthread erfolgen muss, finden Sie heraus, warum der Aufruf langsam ist. Dazu verwenden Sie am besten Perfetto-Traces.
Suchen Sie in den Stapeln nach BinderProxy.transactNative
oder Binderproxy.transact
.
Das bedeutet, dass ein Binder-Aufruf stattfindet. Nach diesen beiden Zeilen sehen Sie die aufgerufene Binder API. Im folgenden Beispiel wird IAccessibilityManager.addClient
aufgerufen.
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
Viele aufeinanderfolgende Binderaufrufe in einer engen Schleife können einen Thread für einen langen Zeitraum blockieren.
Eine blockierende E/A
Blockieren Sie nie E/A-Vorgänge im Hauptthread. Dies ist ein Antimuster.
Konflikt durch Sperre
Wenn ein Thread blockiert wird, wenn eine Sperre eingerichtet wird, kann dies zu einem ANR-Fehler führen.
Das folgende Beispiel zeigt, dass der Hauptthread beim Versuch, eine Sperre abzurufen, blockiert wird:
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 zu viele Elemente in einem einzelnen Frame gerendert werden, kann der Hauptthread während der Dauer des Frames nicht mehr reagieren. Beispiel:
- Es werden viele unnötige Elemente außerhalb des Bildschirms gerendert.
- Verwendung eines ineffizienten Algorithmus wie
O(n^2)
zum Rendern vieler UI-Elemente.
Von anderer Komponente blockiert
Wenn eine andere Komponente, z. B. ein Broadcast-Empfänger, den Hauptthread mehr als fünf Sekunden lang blockiert, kann dies zu ANR-Fehlern bei der Eingabe und einer erheblichen Verzögerung führen.
Vermeiden Sie aufwendige Arbeiten am Hauptthread in Anwendungskomponenten. Führen Sie Broadcast-Empfänger nach Möglichkeit in einem anderen Thread aus.