Gdy wątek UI aplikacji na Androida jest zbyt długi, system wysyła wiadomość wyświetla się komunikat „Aplikacja nie odpowiada”, (ANR). Na tej stronie opisujemy różne typy błędów ANR, sposoby ich diagnozowania i sugestie sposobów ich wyeliminowania. Wszystkie Domyślne zakresy czasu oczekiwania wymienione są dla urządzeń AOSP i Pixel. te godziny mogą się różnić w zależności od producenta OEM.
Pamiętaj, że przy ustaleniu przyczyny błędów ANR warto wiedzieć, odróżniać problemy z systemem od problemów z aplikacją.
Gdy system jest w nieprawidłowym stanie, błędy ANR mogą powodować te problemy:
- Przejściowe problemy z serwerem systemu powodują zwykle, że szybkie wywołania Binder wolno.
- Problemy z serwerem systemu i dużym obciążeniem urządzeń powodują, że wątki aplikacji nie działają zgodnie z harmonogramem.
Jeśli masz taką możliwość, dobrym sposobem na odróżnienie problemów z systemem i aplikacją jest aby używać śladów perfetto:
- Aby sprawdzić, czy główny wątek aplikacji jest zaplanowany, sprawdź stan wątku w Perfetto, aby sprawdzić, czy jest uruchomiony czy aktywny.
- Przejrzyj wątki w
system_server
pod kątem problemów takich jak rywalizacja o blokadę. - W przypadku powolnych wywołań Binder sprawdź wątek odpowiedzi (jeśli występuje), aby dowiedzieć się, dlaczego wolno.
Wejściowy limit czasu wysyłania
Błędy ANR związane z wysyłaniem danych wejściowych występują, gdy główny wątek aplikacji nie odpowiada na dane wejściowe takie jak przesunięcie lub naciśnięcie klawisza. Ponieważ aplikacja działa na pierwszym planie po przekroczeniu limitu czasu wysyłania danych wejściowych, są one prawie zawsze widoczne dla użytkownika i łagodzenie skutków problemu.
Domyślny limit czasu: 5 sekund.
Błędy ANR w wysyłaniu danych wejściowych są zwykle spowodowane problemami w wątku głównym. Jeśli główny Wątek został zablokowany w oczekiwaniu na nałożenie blokady, zaangażowane.
Aby uniknąć błędów ANR związanych z wysyłaniem danych wejściowych, postępuj zgodnie z tymi sprawdzonymi metodami:
- Nie wykonuj operacji blokujących ani długotrwałych w wątku głównym. Rozważ
przy użyciu
StrictMode
, aby wykrywać w wątku głównym. - Zminimalizuj rywalizację o blokadę między wątkiem głównym a innymi wątkami.
- Zminimalizuj zadania niezwiązane z interfejsem użytkownika w głównym wątku, na przykład podczas obsługi transmisji lub działających usług.
Najczęstsze przyczyny
Oto kilka częstych przyczyn błędów ANR związanych z wysyłaniem danych wejściowych i sugerowane rozwiązania tych problemów.
Przyczyna | Skutki | Sugerowane poprawki |
---|---|---|
Powolne wywołanie Binder | Wątek główny wykonuje długie synchroniczne wywołanie Binder. | przenieś rozmowę z głównego wątku lub spróbuj ją zoptymalizować, jeśli: lub właściciel interfejsu API. |
Wiele kolejnych wywołań Binder | Wątek główny wykonuje wiele kolejnych wywołań synchronicznego powiązania. | Nie zapętlaj wywołań funkcji binder. |
Blokowanie I/O | Wątek główny wywołuje blokujące wywołania wejścia-wyjścia, takie jak baza danych lub sieć dostęp. | Usuń wszystkie blokujące operacje wejścia-wyjścia z wątku głównego. |
Rywalizacja o blokady | Wątek główny jest zablokowany podczas oczekiwania na nałożenie blokady. | Ogranicz rywalizację o blokadę między wątkiem głównym a innym wątkiem. Zoptymalizuj powolny kod w drugim wątku. |
Droga ramka | Renderowanie zbyt wielu klatek w jednej klatce, co powoduje poważne zacinanie. | Mniej pracy przy wypożyczaniu ramki. Nie używaj algorytmów n2. Używaj skutecznych komponentów takich jak przewijanie czy stronicowanie, Plecak odrzutowy Biblioteka znaczników. |
Zablokowane przez inny komponent | Działa inny komponent, na przykład odbiornik blokując wątek główny. | Jak najbardziej odejmuj zadania niezwiązane z interfejsem z głównego wątku. Uruchom transmisję odbiorcy w innym wątku. |
Zawieszenie GPU | Zawieszenie GPU to problem systemowy lub sprzętowy, który powoduje i powodować zablokowanie renderowania, i co za tym idzie, i widoczną informację o błędzie związanym z wysyłaniem danych wejściowych. | Zazwyczaj nie ma żadnych poprawek po stronie aplikacji. Jeśli skontaktuj się z zespołem ds. sprzętu w celu rozwiązania problemu. |
Debugowanie
Aby rozpocząć debugowanie, spójrz na podpis klastra ANR w Google Play konsola lub Firebase Crashlytics. Klaster zwykle zawiera górną część ramki podejrzewane o spowodowanie błędu ANR.
Poniższy schemat blokowy pokazuje, jak określić przyczynę przekroczenia limitu czasu wprowadzania danych wejściowych błąd związany z wysyłaniem.
Play Vitals może wykrywać i debugować niektóre z tych częstych przyczyn błędów ANR. Dla: Jeśli na przykład Android Vitals wykryje błąd ANR w związku z rywalizacją o blokadę, może podsumować problem i zalecane rozwiązanie w sekcji Statystyki błędów ANR.
Brak zaznaczonego okna
Z kolei zdarzenia takie jak dotknięcie są wysyłane bezpośrednio do odpowiedniego okna w zależności od działania testowania, zdarzenia takie jak klucze muszą mieć wartość docelową. Jest to tzw. miejsce docelowe okno skupione na obrazie. Na każdym wyświetlaczu jest tylko jedno zaznaczone okno. okno, z którego korzysta użytkownik. Jeśli zaznaczone okno nie można znaleźć. Dane wejściowe powodują błąd ANR bez zaznaczenia. Błąd ANR związany z brakiem skupienia na oknie to typ wejściowego błędu ANR służących do wysyłania danych.
Domyślny limit czasu: 5 sekund.
Najczęstsze przyczyny
Błędy ANR nieukierunkowane na okno są zwykle spowodowane jednym z tych problemów:
- Aplikacja wykonuje zbyt dużo pracy i działa zbyt wolno, aby narysować pierwszą klatkę.
- Nie można zaznaczyć okna głównego. Jeśli okno jest oznaczone jako
FLAG_NOT_FOCUSABLE
, użytkownik nie może wysyłać do niego kluczy ani zdarzeń przycisków.
Kotlin
override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) window.addFlags(WindowManager.LayoutParams.FLAG_FLAG_NOT_FOCUSABLE) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); }
Upłynął limit czasu odbiornika
Błąd ANR odbiornika występuje, gdy odbiornik nie obsługuje
w odpowiednim czasie. Dotyczy odbiorników synchronicznych lub tych, które nie wywołują
goAsync()
, przekroczenie czasu oczekiwania oznacza, że onReceive()
nie zakończyło się w
obecnie się znajdujesz. W przypadku odbiorników asynchronicznych lub odbiorników wywołujących funkcję goAsync()
przekroczenie limitu czasu oznacza
że PendingResult.finish()
nie został wywołany na czas.
Błędy ANR odbiornika wiadomości często występują w tych wątkach:
- Wątek główny, jeśli problem dotyczy powolnego uruchamiania aplikacji.
- Nadajnik komunikatów w wątku, jeśli problem jest powolny, kod z
onReceive()
jest powolny. - Wątki instancji roboczych transmisji, jeśli problem jest powolny podczas transmisji kodu
goAsync()
.
Aby uniknąć błędów ANR odbiornika, postępuj zgodnie z tymi sprawdzonymi metodami:
- Upewnij się, że aplikacja uruchamia się szybko, ponieważ jest uwzględniana w czasie oczekiwania na błąd ANR aplikacja rozpoczyna obsługę transmisji.
- Jeśli jest używany typ
goAsync()
, dopilnuj, by usługaPendingResult.finish()
została szybko wywołana. Podlega to takiej samej wartości czasu oczekiwania dla błędu ANR co w przypadku synchronicznych odbiorników. - Jeśli używana jest usługa
goAsync()
, upewnij się, że wątki robocze nie są udostępniane użytkownikowi inne długotrwałe lub blokujące operacje. - Zastanów się, czy nie użyć
registerReceiver()
do obsługi odbiorników w w wątku innym niż główny, aby uniknąć blokowania kodu interfejsu działającego w wątku głównym.
Okresy oczekiwania
Okresy oczekiwania na odebranie transmisji zależą od tego, czy flaga intencji na pierwszym planie oraz wersję platformy.
Typ intencji | Android 13 i starsze | Android 14 lub nowszy |
---|---|---|
Intencja dotycząca priorytetu na pierwszym planie ( |
10 sekund, |
10–20 sekund w zależności od tego, czy proces ma zbyt dużo CPU |
Intencja dotycząca priorytetu w tle (nie ustawiono |
60 sekund |
60–120 sekund w zależności od tego, czy proces ma za mało CPU |
Aby sprawdzić, czy flaga FLAG_RECEIVER_FOREGROUND
jest ustawiona, poszukaj elementu „flg=” w
Temat błędu ANR i sprawdź obecność elementu 0x10000000
. Jeśli ten bit jest ustawiony,
intencja ma ustawioną wartość FLAG_RECEIVER_FOREGROUND
, więc limit czasu jest krótszy.
Przykładowy obiekt błędu ANR z krótkim czasem oczekiwania na transmisję (10–20 sekund):
Broadcast of Intent { act=android.inent.action.SCREEN_ON flg=0x50200010 }
Przykładowy obiekt błędu ANR z długim czasem oczekiwania na transmisję (60–120 sekund):
Broadcast of Intent { act=android.intent.action.TIME_SET flg=0x25200010 }
Jak mierzony jest czas transmisji
Pomiar czasu trwania transmisji rozpoczyna się po jej wysłaniu
system_server
do aplikacji i kończy, gdy aplikacja zakończy przetwarzanie
transmisję. Jeśli proces aplikacji nie został jeszcze uruchomiony, musi przeprowadzić „zimne”
rozpoczęcia przed upływem limitu czasu ANR. Dlatego powolne uruchamianie aplikacji może
błędy ANR odbiornika.
Ilustracja poniżej przedstawia oś czasu ANR odbiornika komunikatów określonych procesów aplikacji.
Pomiar czasu oczekiwania dla błędu ANR kończy się, gdy odbiornik zakończy przetwarzanie komunikat: kiedy to nastąpi, zależy od tego, czy jest on synchroniczny, z odbiornikiem asynchronicznym.
- W przypadku odbiorników synchronicznych pomiar zatrzymuje się po powrocie funkcji
onReceive()
. - W przypadku odbiorników asynchronicznych pomiar kończy się, gdy:
Funkcja
PendingResult.finish()
jest wywoływana.
Najczęstsze przyczyny
Oto kilka częstych przyczyn błędów ANR odbiornika i zalecane rozwiązania.
Przyczyna | Dotyczy | Co się stało | Proponowane rozwiązanie problemu |
---|---|---|---|
Powolne uruchamianie aplikacji | Wszystkie odbiorniki | Uruchomienie aplikacji „na zimno” trwało zbyt długo. | Zoptymalizuj powolne uruchamianie aplikacji. |
Nie zaplanowano: onReceive() | Wszystkie odbiorniki | Wątek odbiornika był zajęty czymś innym i nie mógł
uruchomić metodę onReceive() . | Nie wykonuj długotrwałe zadania w wątku odbiorcy (lub przenieś odbiorcę do dedykowanych w wątku). |
Wolny nośnik onReceive() | Wszyscy odbiorniki, ale głównie synchroniczne | Uruchomiono metodę onReceive() , ale
zostało zablokowane lub powolne, więc nie zostało ukończone na czas. | Optymalizacja powoli kod odbiorcy. |
Nie zaplanowano zadań odbiorcy asynchronicznego | goAsync()
odbiorcy | Metoda onReceive() próbowała wykonać zadanie
w zablokowanej puli wątków instancji roboczych, więc praca się nie rozpoczęła. |
Optymalizuj powolne lub blokowane połączenia albo używaj różnych wątków do transmisji instancji roboczych w porównaniu z innymi długotrwałymi zadaniami. |
Procesy robocze są powolne lub zablokowane | goAsync() odbiorców |
Gdzieś w wątku instancji roboczej wystąpiła blokująca lub powolna operacja
podczas przetwarzania transmisji. PendingResult.finish
nie zostało wywołane na czas. | Optymalizuj powolny odbiornik async
w kodzie. |
Zapomniałem(-am) zadzwonić do: PendingResult.finish |
goAsync() odbiorców |
W ścieżce kodu brakuje wywołania finish() . |
Upewnij się, że funkcja finish() jest zawsze wywoływana. |
Debugowanie
Na podstawie podpisu klastra i raportu ANR możesz znaleźć wątek, który na którym działa odbiornik, a następnie brakuje konkretnego kodu powoli.
Poniższy schemat blokowy pokazuje, jak ustalić przyczynę transmisji błąd ANR odbiorcy.
Znajdowanie kodu odbiorcy
Konsola Google Play pokazuje klasę odbiorcy i intencje transmisji w błędzie ANR. podpis. Szukaj:
cmp=<receiver class>
act=<broadcast_intent>
Oto przykład podpisu błędu ANR odbiornika:
com.example.app.MyClass.myMethod
Broadcast of Intent { act=android.accounts.LOGIN_ACCOUNTS_CHANGED
cmp=com.example.app/com.example.app.MyAccountReceiver }
Znajdź wątek z metodą onReceive().
Jeśli używasz Context.registerReceiver
do określania niestandardowego modułu obsługi,
to wątek, który uruchamia ten moduł obsługi. W przeciwnym razie jest to wątek główny.
Przykład: niezaplanowane zadania odbiornika asynchronicznego
W tej sekcji przedstawiamy przykład debugowania błędu ANR odbiornika.
Załóżmy, że podpis ANR wygląda tak:
com.example.app.MyClass.myMethod
Broadcast of Intent {
act=android.accounts.LOG_ACCOUNTS_CHANGED cmp=com.example.app/com.example.app.MyReceiver }
Na podstawie podpisu można wywnioskować, że intencja transmisji:
android.accounts.LOG_ACCOUNTS_CHANGED
, a klasa odbiorcy to
com.example.app.MyReceiver
Korzystając z kodu odbiorcy, możesz sprawdzić, czy pula wątków „BG Thread”
[0,1,2,3]" wykona główne czynności konieczne do przetworzenia transmisji. Patrząc na stosy
widać, że wszystkie 4 wątki działające w tle mają ten sam wzorzec:
wykonać wywołanie blokujące, getDataSync
. Ponieważ wszystkie wątki w grupie odbiorców były zajęte,
nie udało się przetworzyć transmisji na czas, co spowodowało błąd ANR.
BG Thread #0 (tid=26) Waiting
at jdk.internal.misc.Unsafe.park(Native method:0)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture:563)
at com.google.common.util.concurrent.ForwardingFuture.get(ForwardingFuture:68)
at com.example.app.getDataSync(<MyClass>:152)
...
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at com.google.android.libraries.concurrent.AndroidExecutorsModule.lambda$withStrictMode$5(AndroidExecutorsModule:451)
at com.google.android.libraries.concurrent.AndroidExecutorsModule$$ExternalSyntheticLambda8.run(AndroidExecutorsModule:1)
at java.lang.Thread.run(Thread.java:1012)
at com.google.android.libraries.concurrent.ManagedPriorityThread.run(ManagedPriorityThread:34)
There are several approaches to fix the issue:
- Find out why
getDataSync
is slow and optimize. - Don't run
getDataSync
on all four BG threads. - More generally, ensure that the BG thread pool isn't saturated with long-running operations.
- Use a dedicated thread pool for
goAsync
worker tasks. - Use an unbounded thread pool instead of the bounded BG thread pool
Example: slow app startup
A slow app startup can cause several types of ANRs, especially broadcast
receiver and execute service ANRs. The cause of an
ANR is likely slow app startup if you see ActivityThread.handleBindApplication
in the main thread stacks.
Execute service timeout
An execute service ANR happens when the app's main thread doesn't start a
service in time. Specifically, a service doesn't finish executing
onCreate()
and onStartCommand()
or onBind()
within the
timeout period.
Default timeout period: 20 seconds for foreground service; 200 seconds for
background service. The ANR timeout period includes the app cold start, if
necessary, and calls to onCreate(), onBind()
, or onStartCommand()
.
To avoid execute service ANRs, follow these general best practices:
- Make sure that app startup is fast, since it's counted in the ANR timeout if the app is started to run the service component.
- Make sure that the service's
onCreate()
,onStartCommand()
, andonBind()
methods are fast. - Avoid running any slow or blocking operations on the main thread from other components; these operations can prevent a service from starting quickly.
Common causes
The following table lists common causes of execute service ANRs and suggested fixes.
Cause | What | Suggested fix |
---|---|---|
Slow app startup | The app takes too long to perform a cold start. | Optimize slow app start. |
Slow onCreate(), onStartCommand (), or
onBind() |
The service component's onCreate(),
onStartCommand (), or onBind() method takes too long to
execute on the main thread. |
Optimize slow code. Move slow operations off the critical path where possible. |
Not scheduled (main thread blocked before onStart() ) |
The app's main thread is blocked by another component before the service can be started. | Move other component's work off the main thread. Optimize other component's blocking code. |
How to debug
From the cluster signature and ANR report in Google Play Console or Firebase Crashlytics, you can often determine the cause of the ANR based on what the main thread is doing.
The following flow chart describes how to debug an execute service ANR.
If you've determined that the execute service ANR is actionable, follow these steps to help resolve the issue:
Find the service component class in the ANR signature. In Google Play Console, the service component class is shown in the ANR signature. In the following example ANR details, it's
com.example.app/MyService
.com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly Executing service com.example.app/com.example.app.MyService
Determine whether the slow or block operation is part of app startup, the service component, or elsewhere by checking for the following important function call(s) in the main threads.
Function call(s) in main thread stacks What it means android.app.ActivityThread.handleBindApplication
App was starting up, so the ANR was caused by slow app start. <ServiceClass>.onCreate()
[...]
android.app.ActivityThread.handleCreateService
Service was being created, so the ANR was likely caused by slow onCreate()
code.<ServiceClass>.onBind()
[...]
android.app.ActivityThread.handleBindService
Service was being bound, so the ANR was likely caused by slow onBind()
code.<ServiceClass>.onStartCommand()
[...]
android.app.ActivityThread.handleServiceArgs
Service was being started, so the ANR was likely caused by slow onStartCommand()
code.For example, if the
onStartCommand()
method in theMyService
class is slow, the main threads will look like this:at com.example.app.MyService.onStartCommand(FooService.java:25) at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4820) at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(unavailable:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2289) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8176) at java.lang.reflect.Method.invoke(Native method:0)
Jeśli nie widzisz żadnych ważnych wywołań funkcji, jest kilka innych możliwości:
- usługa jest uruchomiona lub wyłącza się, co oznacza, że stosy są zbyt późno. W takim przypadku możesz zignorować błąd ANR jako wynik fałszywie pozytywny.
- Działa inny komponent aplikacji, na przykład odbiornik. W tym jeśli wątek główny jest prawdopodobnie zablokowany w tym komponencie, uruchomienia usługi.
Jeśli widzisz wywołanie kluczowej funkcji i możesz określić, gdzie wystąpił błąd ANR co się zwykle dzieje, sprawdź pozostałe stosy wątków głównych, aby dowiedzieć się, i zoptymalizować ją lub przesunąć poza ścieżkę krytyczną.
- Upewnij się, że aplikacja uruchamia się szybko, ponieważ jest uwzględniana w czasie oczekiwania na błąd ANR aplikacja uruchamia dostawcę treści.
- Zadbaj o to, aby zapytania dostawców treści były szybkie.
- Nie wykonuj wielu równoczesnych wywołań wiązania, które mogą blokować wszystkie wątkach powiązań aplikacji.
- Zrzut stosu spóźnionego. Wątek został przywrócony w krótkim okresie między Wywoływanie błędów ANR i zrzucanie stosów. Opóźnienia w Pixelach na urządzeniach z Androidem 13 to około 100 ms, ale może być dłuższy niż 1 s. Opóźnienie w liczbie pikseli na urządzeniach z Androidem 14 wynosi zwykle poniżej 10 ms.
- Błędna atrybucja wątków. Wątek użyty do utworzenia podpisu błędu ANR nie był wątek, który nie odpowiada, który spowodował błąd ANR. W takim przypadku spróbuj wykonać określ, czy błąd ANR należy do tych typów:
- Problem obejmujący cały system. Proces nie został zaplanowany z powodu dużego obciążenia systemu lub na serwerze systemu.
- Pobieranie stosu trwa zbyt długo i przekracza limit czasu.
- Proces przestał lub został zakończony przed przejęciem stosu.
Więcej informacji o usługach można znaleźć na tych stronach:
Dostawca treści nie odpowiada
Błąd ANR dostawcy treści występuje, gdy zdalny dostawca treści trwa dłużej niż po określonym czasie oczekiwania na odpowiedź na zapytanie, co kończy się niepowodzeniem.
Domyślny limit czasu: określany przez dostawcę treści za pomocą atrybutu
ContentProviderClient.setDetectNotResponding
. Limit czasu błędu ANR
zawiera łączny czas wykonywania zapytania dotyczącego zdalnego dostawcy treści, który
obejmuje uruchamianie aplikacji zdalnej „na zimno”, jeśli nie była wcześniej uruchomiona.
Aby uniknąć błędów ANR dostawcy treści, postępuj zgodnie z tymi sprawdzonymi metodami:
Najczęstsze przyczyny
W tabeli poniżej znajdziesz typowe przyczyny błędów ANR dostawcy treści oraz sugerowane naprawiania błędów.
Przyczyna | Skutki | Sygnał | Proponowane rozwiązanie problemu |
---|---|---|---|
Powolne zapytanie dostawcy treści | Realizacja dostawcy treści trwa zbyt długo lub jest zablokowany. | Ramka android.content.ContentProvider$Transport.query
jest w wątku Binder. |
Zapytanie dostawcy treści z optymalizacją. Dowiedz się, co blokuje segregację w wątku. |
Powolne uruchamianie aplikacji | Uruchomienie aplikacji dostawcy treści trwa zbyt długo. | Ramka ActivityThread.handleBindApplication znajduje się w
w wątku głównym. |
Optymalizuj uruchamianie aplikacji. |
Wyczerpanie wątków Bindera – wszystkie wątki są zajęte | Wszystkie wątki powiązania są zajęte obsługą innych żądań synchronicznych, więc Nie można uruchomić wywołania powiązania dostawcy treści. | Aplikacja się nie uruchamia, wszystkie wątki Bindera są zajęte, a zawartość nie jest uruchomiony dostawca. | Zmniejsz obciążenie wątków powiązań. Oznacza to, że należy zmniejszyć liczbę wykonywać połączenia telefoniczne lub mniej pracować przy obsłudze połączeń przychodzących. |
Debugowanie
Aby debugować błąd ANR dostawcy treści, użyj podpisu klastra i raportu ANR w w Konsoli Google Play lub w Firebase Crashlytics, sprawdźcie główny wątek prowadzone przez wątki powiązania.
Poniższy schemat blokowy opisuje sposób debugowania błędu ANR dostawcy treści:
Fragment kodu poniżej pokazuje, jak wygląda wątek powiązania, gdy jest zablokowane z powodu powolnego zapytania dostawcy treści. W tym przypadku dostawca treści Zapytanie oczekuje na blokadę podczas otwierania bazy danych.
binder:11300_2 (tid=13) Blocked
Waiting for osm (0x01ab5df9) held by at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers:182)
at com.example.app.MyClass.blockingGetOpenDatabase(FooClass:171)
[...]
at com.example.app.MyContentProvider.query(MyContentProvider.java:915)
at android.content.ContentProvider$Transport.query(ContentProvider.java:292)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:107)
at android.os.Binder.execTransactInternal(Binder.java:1339)
at android.os.Binder.execTransact(Binder.java:1275)
Poniższy fragment kodu pokazuje, jak wygląda wątek główny, gdy zablokowane z powodu powolnego uruchamiania aplikacji. W tym przypadku aplikacja uruchamia się wolno z powodu rywalizacji o blokadę podczas inicjowania sztyletu.
main (tid=1) Blocked
[...]
at dagger.internal.DoubleCheck.get(DoubleCheck:51)
- locked 0x0e33cd2c (a qsn)at dagger.internal.SetFactory.get(SetFactory:126)
at com.myapp.Bar_Factory.get(Bar_Factory:38)
[...]
at com.example.app.MyApplication.onCreate(DocsApplication:203)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1316)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6991)
at android.app.ActivityThread.-$$Nest$mhandleBindApplication(unavailable:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2235)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8170)
at java.lang.reflect.Method.invoke(Native method:0)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Odpowiedź powolnego zadania
Błąd ANR reakcji na zadanie występuje, gdy reakcja aplikacji trwa zbyt długo
JobService.onStartJob()
lub JobService.onStopJob()
albo trwa to zbyt długo
udostępnij powiadomienie przy użyciu: JobService.setNotification()
. To sugeruje,
główny wątek aplikacji jest blokowany podczas wykonywania innej czynności.
Jeśli problem dotyczy JobService.onStartJob()
lub JobService.onStopJob()
,
sprawdź, co dzieje się w wątku głównym. Jeśli problem dotyczy
JobService.setNotification()
, postaraj się zadzwonić do niego jak najszybciej.
Nie wykonuj zbyt wielu zadań przed wysłaniem powiadomienia.
Tajne błędy ANR
Czasami przyczyna występowania błędu ANR jest niejasna lub niewystarczająca informacje potrzebne do debugowania w podpisie klastra i raporcie ANR. W takich przypadkach nadal możesz wykonać kilka czynności, aby ustalić, czy błąd ANR praktyczne.
Kolejka wiadomości jest bezczynna lub natywne Ankiety
Jeśli widzisz ramkę android.os.MessageQueue.nativePollOnce
w
często wskazuje, że wątek, który prawdopodobnie nie odpowiada, został faktycznie
bezczynny i oczekiwanie na wiadomości typu looper. Szczegóły błędu ANR w Konsoli Google Play
wygląda tak:
Native method - android.os.MessageQueue.nativePollOnce
Executing service com.example.app/com.example.app.MyService
Jeśli na przykład wątek główny jest nieaktywny, stosy wyglądają tak:
"main" tid=1 NativeMain threadIdle
#00 pc 0x00000000000d8b38 /apex/com.android.runtime/lib64/bionic/libc.so (__epoll_pwait+8)
#01 pc 0x0000000000019d88 /system/lib64/libutils.so (android::Looper::pollInner(int)+184)
#02 pc 0x0000000000019c68 /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+112)
#03 pc 0x000000000011409c /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+44)
at android.os.MessageQueue.nativePollOnce (Native method)
at android.os.MessageQueue.next (MessageQueue.java:339) at android.os.Looper.loop (Looper.java:208)
at android.app.ActivityThread.main (ActivityThread.java:8192)
at java.lang.reflect.Method.invoke (Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:626)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1015)
Istnieje kilka powodów, dla których wątek, który prawdopodobnie nie odpowiada, może być nieaktywny:
Brak ramek stosu
Niektóre raporty o błędach ANR nie zawierają grup z błędem ANR, co oznacza, że podczas generowania raportu ANR nie udało się wykonać zrzutu stosu. Jest kilka możliwe przyczyny braku ramek stosu:
[...]
--- CriticalEventLog ---
capacity: 20
timestamp_ms: 1666030897753
window_ms: 300000
libdebuggerd_client: failed to read status response from tombstoned: timeout reached?
----- Waiting Channels: pid 7068 at 2022-10-18 02:21:37.<US_SOCIAL_SECURITY_NUMBER>+0800 -----
[...]
Błędy ANR bez ramek stosu nie wymagają podejmowania działań na podstawie podpisu klastra lub błędu ANR raport. Aby przeprowadzić debugowanie, poszukaj innych klastrów aplikacji, ponieważ jeśli problem jest duży wystarcza zwykle, że ma własny klaster z ramkami stosu. Możesz też skorzystać z śladów perfetto.
Znane problemy
Wstrzymuję licznik czasu w procesie aplikacji na potrzeby jego zakończenia obsługa transmisji przed aktywatorami ANR może nie działać prawidłowo z powodu w asynchroniczny sposób monitorowania błędów ANR.