Есть ли способ узнать, где мое приложение выбросило ANR (приложение не отвечает). Я взглянул на файл traces.txt в / data и увидел след для своего приложения. Это то, что я вижу в след.
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.
Спасибо.
android
performance
android-anr-dialog
lostInTransit
источник
источник
android.os.MessageQueue.nativePollOnce(Native Method)
. Могу ли я безопасно проигнорировать это?Ответы:
ANR происходит, когда в «основном» потоке выполняется какая-то длительная операция. Это поток цикла событий, и если он занят, Android не может обрабатывать какие-либо дальнейшие события GUI в приложении и, таким образом, выдает диалог ANR.
Теперь, в трассе, которую вы разместили, основной поток, кажется, работает нормально, проблем нет. Он находится в бездействии в MessageQueue, ожидая поступления другого сообщения. В вашем случае ANR, скорее всего, была более длительной операцией, а не чем-то, что постоянно блокировало поток, поэтому поток событий восстанавливался после завершения операции, и ваша трассировка прошла после ANR.
Определить, где происходят ANR, легко, если это постоянный блок (например, тупик, получающий некоторые блокировки), но сложнее, если это просто временная задержка. Сначала просмотрите код и найдите уязвимые места и длительные операции. Примеры могут включать в себя использование сокетов, блокировок, спящих потоков и других операций блокировки из потока событий. Вы должны убедиться, что все это происходит в отдельных потоках. Если ничто не кажется проблемой, используйте DDMS и включите представление потока. Это показывает все потоки в вашем приложении, похожие на ваш след. Воспроизведите ANR и обновите основной поток одновременно. Это должно показать вам точно, что происходит во время ANR
источник
Вы можете включить StrictMode на уровне API 9 и выше.
источник
Вы задаетесь вопросом, какая задача содержит поток пользовательского интерфейса. Файл трассировки дает вам подсказку, чтобы найти задачу. вам нужно исследовать состояние каждого потока
Состояние потока
Сосредоточьтесь на состоянии SUSPENDED, MONITOR. Состояние монитора указывает, какой поток исследуется, и состояние потока SUSPENDED, вероятно, является основной причиной тупика.
Основные этапы расследования
Трассировка не всегда содержит «ожидание блокировки». в этом случае трудно найти основную причину.
источник
- waiting to lock an unknown object
внутри"HeapTaskDaemon" daemon prio=5 tid=8 Blocked
. Что это может помочь?Я изучал Android в течение последних нескольких месяцев, так что я далеко не эксперт, но я был очень разочарован документацией по ANR.
Большая часть рекомендаций, похоже, направлена на то, чтобы их избегать или исправлять, слепо просматривая ваш код, и это здорово, но я ничего не смог найти по анализу трассировки.
Есть три вещи, которые вы действительно должны искать с журналами ANR.
1) Взаимные блокировки: когда поток находится в состоянии WAIT, вы можете просмотреть подробную информацию, чтобы определить, кто из них «holdby =». Большую часть времени он будет удерживаться сам по себе, но если он удерживается другим потоком, это может быть признаком опасности. Иди посмотри на эту ветку и посмотри, чем она держится. Вы можете найти петлю, которая является явным признаком того, что что-то пошло не так. Это довольно редко, но это первый момент, потому что когда это происходит, это кошмар
2) Ожидание основного потока: если ваш основной поток находится в состоянии WAIT, проверьте, не поддерживается ли он другим потоком. Этого не должно быть, потому что ваш поток пользовательского интерфейса не должен удерживаться фоновым потоком.
Оба этих сценария означают, что вам необходимо значительно переработать код.
3) Тяжелые операции с основным потоком: это наиболее распространенная причина ANR, но иногда ее сложнее найти и исправить. Посмотрите на основные детали темы. Прокрутите трассировку стека и пока не увидите классы, которые вы узнаете (из вашего приложения). Посмотрите на методы в трассировке и выясните, выполняете ли вы сетевые вызовы, вызовы БД и т. Д. В этих местах.
Наконец, и я прошу прощения за бесстыдное подключение моего собственного кода, вы можете использовать анализатор журналов python, который я написал по адресу https://github.com/HarshEvilGeek/Android-Log-Analyzer. Это позволит вам просмотреть ваши файлы журналов, открыть файлы ANR, найти тупики, находите ожидающие основные потоки, находите неперехваченные исключения в журналах вашего агента и печатайте все это на экране относительно легко читаемым способом. Прочитайте файл ReadMe (который я собираюсь добавить), чтобы узнать, как его использовать. Это помогло мне за последнюю неделю!
источник
Всякий раз, когда вы анализируете проблемы синхронизации, отладка часто не помогает, поскольку остановка приложения в точке останова устранит проблему.
Лучше всего вставить множество журналов вызовов (Log.XXX ()) в различные потоки и обратные вызовы приложения и посмотреть, где задержка. Если вам нужна трассировка стека, создайте новое исключение (просто создайте его экземпляр) и зарегистрируйте его.
источник
Что запускает ANR?
Как правило, система отображает ANR, если приложение не может ответить на ввод пользователя.
В любой ситуации, когда ваше приложение выполняет потенциально длительную операцию, вы не должны выполнять работу над потоком пользовательского интерфейса, а вместо этого создавать рабочий поток и выполнять большую часть работы там. Это поддерживает работу потока пользовательского интерфейса (который управляет циклом событий пользовательского интерфейса) и предотвращает вывод системы о том, что ваш код заморожен.
Как избежать ANR
Приложения Android обычно работают полностью в одном потоке (по умолчанию «поток пользовательского интерфейса» или «основной поток»). Это означает, что все, что ваше приложение делает в потоке пользовательского интерфейса, выполнение которого занимает много времени, может вызвать диалог ANR, поскольку ваше приложение не дает себе возможности обрабатывать входное событие или намеренные широковещательные рассылки.
Поэтому любой метод, который выполняется в потоке пользовательского интерфейса, должен выполнять как можно меньше работы в этом потоке. В частности, действия должны делать как можно меньше для настройки в ключевых методах жизненного цикла, таких как onCreate () и onResume (). Потенциально длительные операции, такие как операции с сетью или базой данных, или вычислительно дорогостоящие вычисления, такие как изменение размера растровых изображений, должны выполняться в рабочем потоке (или в случае операций с базами данных посредством асинхронного запроса).
Код: рабочий поток с классом AsyncTask
Код: выполнение рабочего потока
Чтобы выполнить этот рабочий поток, просто создайте экземпляр и вызовите execute ():
Источник
http://developer.android.com/training/articles/perf-anr.html
источник
моя проблема с ANR, после большой работы я обнаружил, что поток вызывает ресурс, который не существует в макете, вместо возврата исключения я получил ANR ...
источник
Вам нужно искать «ожидание блокировки» в файле /data/anr/traces.txt
для более подробной информации: Инженер для высокой производительности с инструментами от Android & Play (Google I / O '17)
источник
Основываясь на ответе @Horyun Lee, я написал небольшой скрипт на python, чтобы помочь исследовать ANR
traces.txt
.ANR будут выводиться в виде графики,
graphviz
если вы установилиgrapvhviz
в вашей системе.Png будет выводиться, как показано ниже, если в файле обнаружены ANR
traces.txt
. Это более интуитивно понятно.Пример
traces.txt
файла, использованного выше, был получен отсюда .источник
Подумайте об использовании библиотеки ANR-Watchdog для точного отслеживания и захвата трассировок стека ANR с высоким уровнем детализации. Затем вы можете отправить их в свою библиотеку отчетов о сбоях. Я рекомендую использовать
setReportMainThreadOnly()
в этом сценарии. Вы можете либо заставить приложение генерировать нефатальное исключение точки замораживания, либо заставить приложение принудительно завершать работу, когда происходит ANR.Обратите внимание, что стандартные отчеты ANR, отправляемые на вашу консоль разработчика Google Play, часто не достаточно точны, чтобы точно определить проблему. Вот почему нужна сторонняя библиотека.
источник