Znajdź wątek, który nie odpowiada

Ten dokument pokazuje, jak znaleźć wątek, który nie odpowiada w stosie błędów ANR dump. Wątek, który nie odpowiada, różni się w zależności od typu błędu ANR, jak pokazano tutaj tabeli.

Typ błędu ANR Wątek nie odpowiada
Wejściowy dyspozytor Wątek główny
Dyspozytor danych wejściowych bez zaznaczenia okna Wątek główny. Ten typ błędu ANR zwykle nie jest spowodowany zablokowaniem w wątku.
Odbiornik transmisji (synchroniczny) Wątek jest uruchomiony onReceive() Jest to wątek główny, chyba że niestandardowy moduł obsługi w wątku innym niż główny jest określono za pomocą Context.registerReceiver
Odbiornik transmisji (asynchroniczny) Sprawdź kod, aby dowiedzieć się, za który wątek lub pula wątków odpowiada podczas przetwarzania transmisji goAsync .
Wykonuję limit czasu usługi Wątek główny
Rozpoczęcie usługi na pierwszym planie Wątek główny
Dostawca treści nie odpowiada Wykonaj 1 z tych czynności:
  • Wątek powiązania, jeśli błąd ANR jest spowodowany powolnym dostawcą treści zapytania.
  • Wątek główny, jeśli błąd ANR jest spowodowany długim uruchomieniem aplikacji.
Brak odpowiedzi na onStartJob lub onStopJob Wątek główny

Czasami wątek nie odpowiada z powodu głównej przyczyny w innym wątku lub procesu. Wątek może nie odpowiadać z powodu oczekiwania na:

  • Blokada naciśnięta przez inny wątek.
  • Powolne wywołanie Binder do innego procesu.

Najczęstsze przyczyny braku odpowiedzi w wątkach

Poniżej znajdziesz typowe przyczyny braku odpowiedzi w wątkach.

Powolne wywołanie Binder

Choć większość wywołań binder jest szybkie, „długi ogon” może być bardzo powolny. To jest występuje częściej, jeśli urządzenie jest załadowane lub gdy wątek odpowiedzi w powiązaniu jest powolne, np. z powodu rywalizacji o blokadę, wielu przychodzących połączeń telefonicznych lub sprzętu czasu oczekiwania warstwy abstrakcji (HAL).

Możesz rozwiązać ten problem, przenosząc synchroniczne wywołania Binder do wątków w tle gdy tylko jest to możliwe. Jeśli wywołanie musi odbyć się w wątku głównym, dowiedz się, dlaczego jest powolne. Najlepszy sposób to zrobić ze śladów Perfetto.

Poszukaj w grupach tych elementów: BinderProxy.transactNative lub Binderproxy.transact. Oznacza to, że trwa wywołanie Binder. Po tych 2 wierszach widać interfejsu API binder. W poniższym przykładzie wywołaniem ma być 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 kolejnych wywołań Binder w ścisłej pętli może zablokować wątek przez długi czas.

blokujące I/O

Nigdy nie blokuj wejścia-wyjścia w wątku głównym. To jest antywzorzec.

Rywalizacja o blokadę

Zablokowanie wątku podczas uzyskiwania blokady może spowodować błąd ANR.

W przykładzie poniżej widać, że wątek główny jest blokowany podczas próby pozyskania blokada:

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

Droga ramka

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

  • renderowanie wielu niepotrzebnych elementów niewidocznych na ekranie,
  • przy korzystaniu z niewydajnego algorytmu, np. O(n^2), podczas renderowania wielu elementów UI. .

Zablokowane przez inny komponent

Jeśli inny komponent, np. odbiornik, zablokuje wątek główny dłużej niż 5 sekund, może to spowodować błędy ANR związane z wysyłaniem danych wejściowych i poważne zacinanie.

Unikaj wykonywania wielu pracy nad głównym wątkiem w komponentach aplikacji. Uruchom transmisję w miarę możliwości – w innym wątku.