Znajdź wątek, który nie odpowiada

Ten dokument pokazuje, jak znaleźć nieodpowiadający wątek w zrzucie stosu ANR. Wątek, który nie odpowiada, różni się w zależności od typu błędu ANR, co pokazano w tabeli poniżej.

Typ błędu ANR Wątek nie odpowiada
Wysyłanie danych wejściowych Wątek główny
Brak aktywnego okna wysyłania danych wejściowych Wątek główny. Ten typ błędu ANR zwykle nie jest spowodowany zablokowanym wątkiem.
Odbiornik transmisji (synchroniczny) Wątek uruchomiony onReceive(). To jest wątek główny, chyba że w wątku innym niż główny określisz niestandardową obsługę za pomocą funkcji Context.registerReceiver.
Odbiornik transmisji (asynchroniczny) Sprawdź kod, aby zobaczyć, który wątek lub pula wątków odpowiada za przetwarzanie transmisji po wywołaniu funkcji goAsync.
Czas oczekiwania usługi jest wykonywany Wątek główny
Rozpoczęcie usługi działającej na pierwszym planie Wątek główny
Dostawca treści nie odpowiada Wykonaj 1 z tych czynności:
  • Wątek Binder, jeśli błąd ANR jest spowodowany powolnym zapytaniem dostawcy treści.
  • Wątek główny, jeśli błąd ANR jest spowodowany długim uruchamianiem aplikacji.
Brak odpowiedzi na żądania onStartJob lub onStopJob Wątek główny

Czasami wątek nie odpowiada z powodu głównej przyczyny w innym wątku lub w innym procesie. Wątek może nie odpowiadać, ponieważ:

  • Blokada natrzymywana przez inny wątek.
  • Powolne wywołanie Binder do innego procesu.

Najczęstsze przyczyny braku odpowiedzi wątków

Oto częste przyczyny braku odpowiedzi wątków.

Powolne wywołanie Binder

Choć większość wywołań pośrednich jest szybkich, te ostatnie mogą być bardzo powolne. Jest to bardziej prawdopodobne, jeśli urządzenie zostanie wczytane lub gdy wątek odpowiedzi powiązania działa powolnie, na przykład w wyniku rywalizacji o blokadę, wielu przychodzących wywołań Binder lub przekroczenia limitu czasu oczekiwania na warstwę abstrakcji sprzętowej (HAL).

Aby rozwiązać ten problem, przenieś synchroniczne wywołania Binder do wątków w tle, gdy tylko jest to możliwe. Jeśli wywołanie musi mieć miejsce w wątku głównym, dowiedz się, dlaczego jest powolne. Najlepiej wykorzystać ślady Perfetto.

Szukaj w grupach BinderProxy.transactNative lub Binderproxy.transact. Oznacza to, że ma miejsce wywołanie Binder. Po tych 2 wierszach pojawi się wywoływany interfejs API Binder. W poniższym przykładzie wywołanie to 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)
...

Wiele kolejnych wywołań Binder

Wykonywanie wielu następujących po sobie wywołań binder w ścisłej pętli może zablokować wątek na dłuższy czas.

Blokowanie wejścia-wyjścia

Nigdy nie wykonuj blokowania wejścia-wyjścia w wątku głównym. To jest antywzór.

Rywalizacja o blokadę

Jeśli wątek jest zablokowany podczas uzyskiwania blokady, może to spowodować błąd ANR.

Ten przykład pokazuje, że wątek główny jest blokowany podczas próby uzyskania blokady:

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

Wątek blokujący wysyła żądanie HTTP do pobrania filmu:

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

Drogie kadrowanie

Renderowanie zbyt wielu rzeczy w jednej ramce może spowodować, że wątek główny nie będzie odpowiadać przez cały czas wyświetlania klatki, na przykład:

  • Renderowanie wielu zbędnych elementów poza ekranem.
  • stosowanie nieefektywnego algorytmu, takiego jak O(n^2), podczas renderowania wielu elementów interfejsu;

Zablokowane przez inny komponent

Jeśli inny komponent, na przykład odbiornik, blokuje wątek główny na ponad 5 sekund, może to spowodować błędy ANR w wysyłaniu danych wejściowych i poważne zacinanie.

Unikaj wykonywania zbyt ciężkich czynności w wątku głównym w komponentach aplikacji. W miarę możliwości uruchom odbiorniki w innym wątku.