Android - как я могу расследовать ANR?

голоса
121

Есть ли способ узнать, где мое приложение бросило ANR (приложение не отвечает). Я посмотрел на файл traces.txt в / данных, и я вижу след для моего приложения. Это то, что я вижу в след.

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

Как я могу узнать, где проблема? Методы в трассировке все методы SDK.

Благодарю.

Задан 01/04/2009 в 07:28
источник пользователем
На других языках...                            


10 ответов

голоса
107

ANR происходит, когда некоторая длительная эксплуатация происходит в «главном» поток. Это поток событий цикла, и если он занят, Android не может обрабатывать любые дальнейшие события интерфейса в приложении, и, таким образом, бросает в диалог ANR.

Теперь, в след вы в курсе, основной поток, кажется, все в порядке, нет никаких проблем. Он работает на холостом ходу в MessageQueue, ожидая еще одно сообщение, чтобы войти. В вашем случае ANR был вероятно больше операция, а не то, что заблокировала нить постоянно, так что поток событий восстанавливается после операции завершена, и ваш след прошел через после того, как НР.

Детектирование где ANR: произойдет легко, если это постоянный блок (тупиковая приобретение некоторых замков, например), но сложнее, если это просто временная задержка. Во-первых, перейти на код и посмотреть на пятна и восприимчивы долго работающих операций. Примеры могут включать использование розетки, замки, нитку спят, а другие блокирующие операции внутри потока событий. Вы должны убедиться, что все они происходят в отдельных потоках. Если ничего не кажется проблемой, используйте DDMS и включить просмотр потока. Это показывает все потоки в приложении похожие на след у вас есть. Воспроизведите ANR и обновить основной поток одновременно. Это должно показать вам точно, что происходит во время НРУ

Ответил 01/04/2009 d 21:59
источник пользователем

голоса
86

Вы можете включить StrictMode в уровне API 9 и выше.

StrictMode наиболее часто используется , чтобы поймать случайный доступ к диску или сетей на главном потоке приложения, где операции UI принимаются и анимация имеет место. Сохраняя основной поток вашего приложения в ответ, вы также предотвратить ANR диалоговые окна не показывались пользователям.

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

с помощью penaltyLog()вы можете смотреть вывод ADB LogCat в то время как вы используете приложение , чтобы увидеть нарушение , как они происходят.

Ответил 29/07/2011 d 10:00
источник пользователем

голоса
48

Вы хотите знать, какая задача держать UI тему. Файл трассировки дает вам подсказку, чтобы найти задачу. вам необходимо исследовать состояние каждого потока

Состояние резьбы

  • бег - выполнение кода приложения
  • Спальный - называется Thread.sleep ()
  • монитор - ожидание, чтобы получить блокировку монитора
  • ждать - в Object.wait ()
  • родной - выполнение нативного кода
  • vmwait - ожидание ресурса В.М.
  • зомби - поток находится в процессе умирания
  • INIT - поток инициализации (вы не должны видеть это)
  • начиная - нить собирается начать (вы не должны видеть это либо)

Сосредоточьтесь на SUSPENDED, MONITOR состояние. Монитор состояния указывает на то, какой поток исследован и взвешенном состоянии нити, вероятно, основной причиной тупика.

Основные шаги расследования

  1. Найти «ждет, чтобы заблокировать»
    • вы можете найти состояние монитора "Binder Thread # 15" PRIO = 5 TID = 75 MONITOR
    • Вам повезло, если найти «ждет, чтобы заблокировать»
    • Пример: ожидание блокировки <0xblahblah> (а com.foo.A) проводится ThreadId = 74
  2. Вы можете заметить, что «TID = 74» держать задачу сейчас. Так что в TID = 74
  3. TID = 74 может быть взвешенное состояние! найти главную причину!

следы не всегда содержат «ожидающую блокировку». в этом случае трудно найти основную причину.

Ответил 15/07/2014 d 16:03
источник пользователем

голоса
9

Я изучаю андроид в течение последних нескольких месяцев, так что я далек от эксперта, но я был очень разочарован с документацией на ANRS.

Большинство советов, как представляется, направлены на их избежать или фиксируя их, слепо глядя через код, который является большим, но я не мог найти что-либо на анализе следов.

Есть три вещи, которые вам действительно нужно искать с бревнами ANR.

1) ТУПИКИ: Когда поток находится в состоянии WAIT, вы можете просматривать детали, чтобы узнать, кто это «heldby =». Большая часть времени, она будет проходить сам по себе, но если он принадлежит другому потоку, что, скорее всего, будет знаком опасности. Посмотрите на эту нить и посмотреть, что он принадлежит. Вы могли бы найти петлю, которая является явным признаком того, что что-то пошло не так. Это довольно редкое, но это первая точка, потому что, когда это произойдет, это кошмар

2) Основная нить ожидания: Если ваш основной поток находится в состоянии ожидания, проверьте, если он принадлежит другому потоку. Это не должно было случиться, потому что Ваш поток пользовательского интерфейса не должны проводиться на фоне потока.

Оба из этих сценариев, значит, вам нужно переделать код значительно.

3) тяжелые операции на основном потоке: Это наиболее частая причина ANRS, но иногда один из труднее найти и исправить. Посмотрите на основных деталях резьбы. Прокрутка вниз трассировки стека и до тех пор, пока не увидите классы вы узнаете (из приложения). Посмотрите на методы в трассировке и выяснить, если вы делаете сетевые вызовы, Д.Б. звонки и т.д. в этих местах.

Наконец, и я извиняюсь за бесстыдно подключить свой собственный код, вы можете использовать анализатор лог питона , который я написал в https://github.com/HarshEvilGeek/Android-Log-Analyzer Это будет проходить через ваши лог - файлы, открытые файлы ANR, найти тупики, найти ждут основные темы, найти пойманные исключения в журналах агентов и распечатать все это на экране в относительно легко читаемом образом. Прочитайте файл ReadMe (который я собираюсь добавить) , чтобы узнать , как использовать его. Это помогло мне тонну в последней неделе!

Ответил 08/08/2014 d 08:14
источник пользователем

голоса
4

Всякий раз, когда вы анализируя проблемы синхронизации, отладка часто не помогает, как замораживание приложения в контрольной точке сделает проблему уйти.

Лучше всего, чтобы вставить много лесозаготовительных вызовы (Log.XXX ()) в различные потоки и обратные вызовы в приложении и посмотреть, где задержка в. Если вам нужен StackTrace, создать новую Exception (только один экземпляр) и зарегистрировать ее.

Ответил 18/02/2011 d 21:26
источник пользователем

голоса
3

Что Триггеры ANR?

В целом, система отображает ANR, если приложение не может реагировать на ввод данных пользователя.

В любой ситуации, в которой ваше приложение выполняет потенциально длительную операцию, вы не должны выполнять работу в потоке пользовательского интерфейса, но вместо того, чтобы создать рабочий поток и сделать большую часть работы там. Это держит поток пользовательского интерфейса (который приводит в действие события цикла пользовательский интерфейс) работает и не позволяет системе сделать вывод, что ваш код замерзла.

Как избежать ошибок ANR

Android приложения обычно работают исключительно на одном потоке, по умолчанию «UI нить» или «основной поток»). Это означает, что что-то ваше приложение делает в потоке пользовательского интерфейса, который занимает много времени для завершения может вызвать диалоговое окно ANR, потому что приложение не дает себе шанс для обработки события ввода или намерений передачи.

Таким образом, любой метод, который работает в потоке пользовательского интерфейса должен делать, как мало работы, как это возможно на эту тему. В частности, необходимо сделать как можно меньше, чтобы установить в ключевых методах жизненного цикла, такие как OnCreate () и onResume (). Потенциально длительные операции, такие как сети или базы данных операции, или вычислительно дорогие вычисления, такие как изменение размера растровых изображения должны быть сделаны в рабочем потоке (или в случае операций базы данных, с помощью асинхронного запроса).

Код: Рабочий поток с классом AsyncTask

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");
    }
}

Код: Выполнение рабочего потока

Для выполнения этого рабочего потока, просто создать экземпляр и вызвать выполнение ():

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

Источник

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

Ответил 25/04/2014 d 10:14
источник пользователем

голоса
1

Вы должны искать «ждать , чтобы заблокировать» в /data/anr/traces.txt файле

введите описание изображения здесь

для получения более подробной информации: инженер по High Performance с инструментами от Android & Play (Google I / O '17)

Ответил 18/05/2017 d 07:27
источник пользователем

голоса
1

моя проблема с НР, после того, как много работы, я обнаружил, что нить звонит ресурс, который не существует в макете, вместо того, чтобы возвратить исключение, я получил ANR ...

Ответил 06/02/2017 d 08:15
источник пользователем

голоса
0

Рассмотрите возможность использования ANR-сторожевую библиотеки точно отслеживать и стек захват ANR следов на высоком уровне детализации. Вы можете отправить их на аварии отчетности библиотеки. Я рекомендую использовать setReportMainThreadOnly()в этом сценарии. Вы можете сделать приложение бросить несмертельную исключение точки замерзания, или сделать приложение силы бросить курить , когда ANR происходит.

Обратите внимание, что стандартные ANR отчеты отправлены в консоли Play Developer Google часто не достаточно точны, чтобы точно определить проблему. Вот почему сторонняя библиотека требуется.

Ответил 07/08/2017 d 09:38
источник пользователем

голоса
0

Основной на @Horyun Ли ответ, я написал небольшой питон скрипт , чтобы помочь расследовать ANR от traces.txt.

ANR : будет выводиться в графике , graphvizесли вы установили grapvhvizна вашей систему.

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

Детский выход будет , как показано ниже , если есть ANR : обнаруженный в файле traces.txt. Это более интуитивным.

введите описание изображения здесь

Образец traces.txtфайл , используемый выше , был получить от здесь .

Ответил 11/07/2017 d 10:10
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more