Android-jak zbadać ANR?

Czy istnieje sposób, aby dowiedzieć się, gdzie moja aplikacja rzuciła ANR(aplikacja nie odpowiada). Przyjrzałem się śladom.plik txt w /data i widzę ślad dla mojej aplikacji. To jest to, co widzę w śledzeniu.

DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
  | group="main" sCount=1 dsCount=0 s=0 obj=0x400143a8
  | sysTid=691 nice=0 sched=0/0 handle=-1091117924
  at java.lang.Object.wait(Native Method)
  - waiting on <0x1cd570> (a android.os.MessageQueue)
  at java.lang.Object.wait(Object.java:195)
  at android.os.MessageQueue.next(MessageQueue.java:144)
  at android.os.Looper.loop(Looper.java:110)
  at android.app.ActivityThread.main(ActivityThread.java:3742)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:515)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
  at dalvik.system.NativeStart.main(Native Method)

"Binder Thread #3" prio=5 tid=15 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x434e7758
  | sysTid=734 nice=0 sched=0/0 handle=1733632
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #2" prio=5 tid=13 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x433af808
  | sysTid=696 nice=0 sched=0/0 handle=1369840
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #1" prio=5 tid=11 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x433aca10
  | sysTid=695 nice=0 sched=0/0 handle=1367448
  at dalvik.system.NativeStart.run(Native Method)

"JDWP" daemon prio=5 tid=9 VMWAIT
  | group="system" sCount=1 dsCount=0 s=0 obj=0x433ac2a0
  | sysTid=694 nice=0 sched=0/0 handle=1367136
  at dalvik.system.NativeStart.run(Native Method)

"Signal Catcher" daemon prio=5 tid=7 RUNNABLE
  | group="system" sCount=0 dsCount=0 s=0 obj=0x433ac1e8
  | sysTid=693 nice=0 sched=0/0 handle=1366712
  at dalvik.system.NativeStart.run(Native Method)

"HeapWorker" daemon prio=5 tid=5 VMWAIT
  | group="system" sCount=1 dsCount=0 s=0 obj=0x4253ef88
  | sysTid=692 nice=0 sched=0/0 handle=1366472
  at dalvik.system.NativeStart.run(Native Method)

----- end 691 -----

Jak mogę dowiedzieć się, gdzie jest problem? Wszystkie metody w śledzeniu są metodami SDK.

Dzięki.
Author: skaffman, 2009-04-01

10 answers

ANR ma miejsce, gdy w "głównym" wątku odbywa się jakaś długa operacja. Jest to wątek pętli zdarzeń, a jeśli jest zajęty, Android nie może przetworzyć żadnych dalszych zdarzeń GUI w aplikacji, a tym samym wyświetla okno dialogowe ANR.

Teraz, w ślad, który napisałeś, główny wątek wydaje się dobrze, nie ma problemu. Jest na biegu jałowym w wiadomości, czeka na kolejną wiadomość. W Twoim przypadku ANR był prawdopodobnie dłuższą operacją, a nie czymś, co zablokowało wątek na stałe, więc wątek zdarzenia odzyskał się po zakończeniu operacji, a Twój ślad przeszedł po ANR.

Wykrywanie miejsca wystąpienia ANRs jest łatwe, jeśli jest to stały blok (na przykład blokada), ale trudniejsze, jeśli jest to tylko tymczasowe opóźnienie. Po pierwsze, przejrzyj swój kod i poszukaj niezliczonych miejsc i długotrwałych operacji. Przykłady mogą obejmować używanie gniazd, blokad, uśpienia wątków i innych operacji blokowania z poziomu wątku zdarzenia. Powinieneś upewnij się, że to wszystko dzieje się w oddzielnych wątkach. Jeśli nic nie wydaje się problemem, użyj DDMS i włącz widok wątku. To pokazuje wszystkie wątki w aplikacji podobne do śladu, który masz. Odtwórz ANR i odśwież główny wątek w tym samym czasie. To powinno pokazać dokładnie, co się dzieje w czasie ANR

 109
Author: sooniln,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-01 20:59:06

Możesz włączyć StrictMode na poziomie API 9 i wyższym.

StrictMode jest najczęściej używany do przechwytywania przypadkowego dysku lub sieci dostęp do głównego wątku aplikacji, gdzie operacje UI są odbierane i animacje odbywają się. Utrzymując główny wątek aplikacji responsywny, zapobiegasz również wyświetlaniu użytkownikom okien dialogowych ANR .

public void onCreate() {
    StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                           .detectAll()
                           .penaltyLog()
                           .penaltyDeath()
                           .build());
    super.onCreate();
}

Używając penaltyLog() możesz oglądać wyjście adb logcat podczas użyj swojego wniosek, aby zobaczyć naruszenia, jak się zdarzają.

 88
Author: Dheeraj V.S.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-07 09:34:50

Zastanawiasz się, które zadanie posiada wątek UI. Plik śledzenia daje podpowiedź, aby znaleźć zadanie. musisz zbadać stan każdego wątku

Stan wątku

  • uruchamianie-wykonywanie kodu aplikacji
  • spanie-tzw. wątek.sleep ()
  • monitor-oczekiwanie na uzyskanie blokady monitora
  • obiekt oczekujący.wait ()
  • native-wykonywanie kodu natywnego
  • vmwait-oczekiwanie na zasób VM
  • Zombie-wątek jest w trakcie umierania
  • INIT-thread jest inicjalizujący (nie powinieneś tego widzieć)
  • starting-thread zaraz się rozpocznie (tego też nie powinieneś widzieć)

Skoncentruj się na zawieszeniu, stanie monitora. Stan monitora wskazuje, który wątek jest badany, a stan zawieszenia wątku jest prawdopodobnie głównym powodem blokady.

Podstawowe kroki

  1. Znajdź " czekanie na blokadę"
    • można znaleźć Stan monitora "wątek segregatora #15" prio=5 tid=75 MONITOR
    • masz szczęście, jeśli znajdziesz "czekanie na blokadę"
    • przykład: waiting to lock (a com.foo.A) trzymane przez threadid=74
  2. możesz zauważyć, że" tid=74 " wstrzymuje zadanie. Więc przejdź do tid=74
  3. tid = 74 znajdź główny powód!

Trace nie zawsze zawiera "waiting to lock". w tym przypadku trudno jest znaleźć główny powód.

 57
Author: Horyun Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-15 15:03:37

Od kilku miesięcy uczę się Androida, więc daleko mi do eksperta, ale naprawdę zawiodłem się na dokumentacji ANRs.

Większość porad wydaje się być nastawiona na unikanie ich lub naprawianie przez ślepe przeglądanie kodu, co jest świetne, ale nie mogłem znaleźć nic na analizę śladu.

Są trzy rzeczy, których naprawdę musisz szukać z dziennikami ANR.

1) Deadlocks: gdy wątek jest w stanie oczekiwania, można spojrzeć poprzez szczegóły, aby dowiedzieć się, kto to jest " heldby=". Przez większość czasu będzie trzymana sama, ale jeśli będzie trzymana przez inny wątek, prawdopodobnie będzie to znak zagrożenia. Spójrz na ten wątek i zobacz, co go trzyma. Możesz znaleźć pętlę, która jest wyraźnym znakiem, że coś poszło nie tak. Jest to dość rzadkie, ale to pierwszy punkt, ponieważ kiedy to się dzieje, to koszmar

2) główny wątek oczekujący: jeśli główny wątek jest w stanie oczekiwania, sprawdź, czy jest utrzymywany przez inny wątek. To nie powinno się zdarzyć, ponieważ wątek interfejsu użytkownika nie powinien być utrzymywany przez wątek w tle.

Oba te scenariusze oznaczają, że musisz znacząco przerobić kod.

3) ciężkie operacje na głównym wątku: jest to najczęstsza przyczyna ANRs, ale czasami jedna z trudniejszych do znalezienia i naprawienia. Spójrz na szczegóły głównego wątku. Przewiń ślad stosu w dół, aż zobaczysz rozpoznane klasy(z aplikacji). Spójrz na metody w śledzeniu i dowiedz się, czy tworzysz sieć wywołania, wywołania db itp. w tych miejscach.

Wreszcie i przepraszam za bezwstydne podpięcie własnego kodu, możesz użyć pythonowego analizatora logów, który napisałem pod https://github.com/HarshEvilGeek/Android-Log-Analyzer to przejrzy Twoje pliki dziennika, otworzy pliki ANR, znajdzie martwe punkty, znajdzie oczekujące główne wątki, znajdzie nieobciążone wyjątki w dziennikach agenta i wydrukuje to wszystko na ekranie w stosunkowo łatwy do odczytania sposób. Przeczytaj plik ReadMe (który zamierzam dodać), aby dowiedzieć się, jak żeby go użyć. Pomogło mi to w zeszłym tygodniu!

 9
Author: Akhil Cherian Verghese,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-08 07:14:57

Gdy analizujesz problemy z czasem, debugowanie często nie pomaga, ponieważ zamrożenie aplikacji w punkcie przerwania sprawi, że problem zniknie.

Najlepiej wstawić wiele połączeń logowania (Log.XXX()) w różnych wątkach i wywołaniach aplikacji i zobacz, gdzie jest opóźnienie. Jeśli potrzebujesz stacktrace, utwórz nowy wyjątek (wystarczy utworzyć instancję) i zaloguj go.

 4
Author: Ulrich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-18 20:26:54

Co wywołuje ANR?

Ogólnie, system wyświetla ANR, jeśli aplikacja nie może odpowiedzieć na dane użytkownika.

W każdej sytuacji, w której aplikacja wykonuje potencjalnie długą operację, nie należy wykonywać pracy nad wątkiem interfejsu użytkownika, ale zamiast tego utworzyć wątek roboczy i wykonać większość pracy w nim. Dzięki temu wątek interfejsu użytkownika (który napędza pętlę zdarzeń interfejsu użytkownika) jest uruchomiony i uniemożliwia systemowi stwierdzenie, że Twój kod został zamrożony.

Jak uniknąć ANRs

Aplikacje na Androida normalnie działają w całości na pojedynczym wątku domyślnie "wątek UI" lub "wątek główny"). Oznacza to, że wszystko, co aplikacja robi w wątku interfejsu użytkownika, które zajmuje dużo czasu, może wywołać okno dialogowe ANR, ponieważ aplikacja nie daje sobie szansy na obsługę zdarzenia wejściowego lub transmisji intencyjnych.

Dlatego każda metoda uruchamiana w wątku UI powinna wykonać jak najmniej pracy w tym wątku. W szczególności działania powinny zrobić jak najmniej w kluczowych metodach cyklu życia, takich jak OnCreate () i onResume (). Potencjalnie długotrwałe operacje, takie jak operacje sieciowe lub bazodanowe, lub kosztowne obliczeniowo obliczenia, takie jak zmiana rozmiaru bitmap, powinny być wykonywane w wątku roboczym (lub w przypadku operacji bazodanowych, poprzez żądanie asynchroniczne).

Code: worker thread with the AsyncTask class

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    // Do the long-running work in here
    protected Long doInBackground(URL... urls) {
        int count = urls.length;
        long totalSize = 0;
        for (int i = 0; i < count; i++) {
            totalSize += Downloader.downloadFile(urls[i]);
            publishProgress((int) ((i / (float) count) * 100));
            // Escape early if cancel() is called
            if (isCancelled()) break;
        }
        return totalSize;
    }

    // This is called each time you call publishProgress()
    protected void onProgressUpdate(Integer... progress) {
        setProgressPercent(progress[0]);
    }

    // This is called when doInBackground() is finished
    protected void onPostExecute(Long result) {
        showNotification("Downloaded " + result + " bytes");
    }
}

Code: Execute worker thread

Aby wykonać ten wątek roboczy, wystarczy tworzenie instancji i wywołanie execute ():

new DownloadFilesTask().execute(url1, url2, url3);

Źródło

Http://developer.android.com/training/articles/perf-anr.html

 3
Author: Jack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-25 09:14:13

Mój problem z ANR, po wielu pracach dowiedziałem się, że wątek wywołuje zasób , który nie istniał w układzie, zamiast zwracać wyjątek, dostałem ANR ...

 1
Author: yaniv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-06 08:15:53

Musisz poszukać "waiting to lock" w /data/anr/traces.txt Plik

Tutaj wpisz opis obrazka

Więcej szczegółów: Inżynier ds. wysokiej wydajności Z Narzędziami z Androida i Play (Google I / O'17)

 1
Author: phnmnn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-26 06:23:02

Basic na @Horyun Lee odpowiedź, napisałem mały skrypt Pythona , aby pomóc zbadać ANR z traces.txt.

ANRs będzie wyświetlany jako grafika przez graphviz, jeśli zainstalowałeś grapvhviz w swoim systemie.

$ ./anr.py --format png ./traces.txt

Png wyświetli się jak poniżej, jeśli w pliku traces.txt wykryto ANRs. To bardziej intuicyjne.

Tutaj wpisz opis obrazka

Przykładowy plik traces.txt użyty powyżej został pobrany z tutaj .

 0
Author: alijandro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-11 10:10:22

Rozważ użycie biblioteki ANR-Watchdog do dokładnego śledzenia i przechwytywania śladów stosu ANR z wysokim poziomem szczegółowości. Następnie możesz wysłać je do biblioteki raportowania awarii. Polecam użycie setReportMainThreadOnly() w tym scenariuszu. Możesz albo sprawić, że aplikacja rzuci nie-fatalny wyjątek punktu zamrożenia, albo zmusić aplikację do zamknięcia, gdy wystąpi ANR.

Należy pamiętać, że standardowe raporty ANR wysyłane do konsoli programisty Google Play często nie są wystarczająco dokładne, aby dokładnie określić problem. Dlatego potrzebna jest biblioteka innej firmy.

 0
Author: Mr-IDE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-03 15:53:29