Trovare il thread che non risponde

Questo documento mostra come identificare il thread che non risponde in uno stack ANR il dump. Il thread che non risponde varia in base al tipo di errore ANR, come mostrato di seguito tabella.

Tipo di ANR Il thread non risponde
Invio dell'input Thread principale
Invio dell'input senza finestra attiva Thread principale. In genere questo tipo di errore ANR non è causato da un errore .
Broadcast receiver (sincrono) Thread in esecuzione onReceive(). Questo è il thread principale, a meno che non venga usato un gestore personalizzato su un thread non principale specificato utilizzando Context.registerReceiver.
Broadcast receiver (asincrono) Controlla il codice per vedere quale thread o pool di thread è responsabile che si occupa di elaborare la trasmissione goAsync .
Esecuzione del timeout del servizio in corso... Thread principale
Inizio servizio in primo piano Thread principale
Il fornitore di contenuti non risponde Una di queste soglie:
  • Thread del bining se l'errore ANR è causato da un fornitore di contenuti lento query.
  • Thread principale se l'errore ANR è causato da un lungo avvio dell'app.
Nessuna risposta a onStartJob o onStopJob Thread principale

A volte il thread non risponde per una causa principale in un thread diverso o processo. Il thread potrebbe non rispondere a causa dell'attesa di quanto segue:

  • Un blocco mantenuto da un altro thread.
  • Una chiamata a binder lenta a un altro processo.

Cause comuni della mancata risposta dei thread

Di seguito sono riportate le cause comuni della mancata risposta dei thread.

Chiamata a Binder lenta

Sebbene la maggior parte delle chiamate a binder sia veloce, la long tail può risultare molto lenta. Questo è più probabile che si verifichi se il dispositivo viene caricato o se viene rallentati, ad esempio a causa del conflitto di blocchi, molte chiamate a Binder in arrivo o Timeout (HAL).

Puoi risolvere il problema spostando le chiamate a binder sincrone nei thread in background ove possibile. Se la chiamata deve avvenire sul thread principale, scopri perché è lenta. Il modo migliore per farlo è tramite le tracce Perfetto.

Cerca BinderProxy.transactNative o Binderproxy.transact nell'elenco filtri. Ciò significa che è in corso una chiamata a raccoglitore. Segui queste due righe, puoi vedere viene chiamata l'API binder. Nell'esempio seguente, la chiamata è 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)
...

Molte chiamate a binder consecutive

L'esecuzione di molte chiamate a binder consecutive in un loop stretto può bloccare un thread per per un lungo periodo.

Un I/O che blocca

Non bloccare mai l'I/O sul thread principale. Questo è un anti-pattern.

Conflitto blocco

Se un thread viene bloccato durante l'acquisizione di un blocco, potrebbe verificarsi un errore ANR.

L'esempio seguente mostra che il thread principale è bloccato durante il tentativo di acquisire un blocco:

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)
[...]

Il thread di blocco sta inviando una richiesta HTTP per scaricare un video:

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)
[...]

Cornice costosa

Eseguire il rendering di troppi elementi in un solo frame può far sì che il thread principale non risponde per la durata del frame, come segue:

  • Rendering di molti elementi non necessari al di fuori dello schermo.
  • Utilizzo di un algoritmo inefficiente, come O(n^2), durante il rendering di molte UI elementi.

Bloccata da un altro componente

Se un altro componente, come un broadcast receiver, blocca il thread principale per più di cinque secondi, può causare errori ANR di invio degli input e gravi jank.

Evita di svolgere operazioni complesse sul thread principale nei componenti dell'app. Esegui trasmissione su un thread diverso, quando possibile.