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:
|
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.