Читать отчеты об ошибках

Ошибки — реальность любого типа разработки, и отчеты об ошибках имеют решающее значение для выявления и решения проблем. Все версии Android поддерживают сбор отчетов об ошибках с помощью Android Debug Bridge (adb) ; Android версии 4.2 и выше поддерживают опцию разработчика для получения отчетов об ошибках и обмена ими по электронной почте, на Диске и т. д.

Отчеты об ошибках Android содержат данные dumpsys , dumpstate и logcat в текстовом формате (.txt), что позволяет легко искать определенный контент. В следующих разделах подробно описаны компоненты отчета об ошибках, описаны распространенные проблемы, а также приведены полезные советы и команды grep для поиска журналов, связанных с этими ошибками. Большинство разделов также содержат примеры вывода команды grep и/или вывода dumpsys .

Логкат

Журнал logcat представляет собой строковый дамп всей информации logcat . Системная часть зарезервирована для фреймворка и имеет более длительную историю, чем основная , которая содержит все остальное. Каждая строка обычно начинается с timestamp UID PID TID log-level , хотя UID может не отображаться в более старых версиях Android.

Просмотр журнала событий

Этот журнал содержит строковые представления сообщений журнала в двоичном формате. Он менее шумный, чем журнал logcat , но его немного труднее читать. При просмотре журналов событий вы можете выполнить поиск в этом разделе по конкретному идентификатору процесса (PID), чтобы узнать, что делал процесс. Основной формат: timestamp PID TID log-level log-tag tag-values ​​.

Уровни журнала включают следующее:

  • В: многословный
  • Д: отладка
  • Я: информация
  • В: предупреждение
  • Э: ошибка

Другие полезные теги журнала событий см. в /services/core/java/com/android/server/EventLogTags.logtags .

Ошибки ANR и взаимоблокировки

Отчеты об ошибках могут помочь вам определить причину ошибок «Приложение не отвечает» (ANR) и событий взаимоблокировки.

Определить не отвечающие приложения

Когда приложение не отвечает в течение определенного времени, обычно из-за заблокированного или занятого основного потока, система завершает процесс и сбрасывает стек в /data/anr . Чтобы обнаружить причину ошибки ANR, выполните поиск am_anr в двоичном журнале событий.

Вы также можете найти ANR in журнале logcat , который содержит дополнительную информацию о том, что использовало процессор во время ANR.

Найти трассировки стека

Часто можно найти трассировки стека, соответствующие ANR. Убедитесь, что временная метка и PID в трассировках виртуальной машины соответствуют исследуемому ANR, а затем проверьте основной поток процесса. Иметь в виду:

  • Основной поток сообщает вам только то, что поток делал во время ANR, что может соответствовать или не соответствовать истинной причине ANR. (Стек в отчете об ошибке может быть невиновным; что-то еще могло зависнуть на долгое время — но недостаточно долго для ANR — прежде чем отсоединиться.)
  • Может существовать более одного набора трассировок стека ( VM TRACES JUST NOW и VM TRACES AT LAST ANR ). Убедитесь, что вы просматриваете правильный раздел.

Найти тупики

Взаимные блокировки часто сначала проявляются как ошибки ANR, поскольку потоки застревают. Если тупиковая ситуация поразит системный сервер, сторожевой таймер в конечном итоге уничтожит его, что приведет к записи в журнале, похожей на: WATCHDOG KILLING SYSTEM PROCESS . С точки зрения пользователя, устройство перезагружается, хотя технически это скорее перезагрузка во время выполнения, чем настоящая перезагрузка.

  • При перезапуске во время выполнения системный сервер отключается и перезапускается; пользователь видит, как устройство возвращается к анимации загрузки.
  • При перезагрузке ядро ​​зависло; пользователь видит, что устройство возвращается к логотипу загрузки Google.

Чтобы обнаружить взаимоблокировки, проверьте разделы трассировки виртуальной машины на наличие шаблона потока A, ожидающего чего-то, удерживаемого потоком B, который, в свою очередь, ожидает чего-то, удерживаемого потоком A.

Деятельность

Activity — это компонент приложения, который предоставляет экран, с которым пользователи взаимодействуют, чтобы сделать что-то, например, набрать номер, сделать фотографию, отправить электронное письмо и т. д. С точки зрения отчета об ошибке, действие — это одно целенаправленное действие, которое может сделать пользователь. , что делает очень важным обнаружение действия, которое было в фокусе во время сбоя. Действия (через ActivityManager) запускают процессы, поэтому обнаружение всех остановок и запусков процессов для данного действия также может помочь в устранении неполадок.

Просмотр целевых действий

Чтобы просмотреть историю целенаправленных действий, выполните поиск am_focused_activity .

Процесс просмотра начинается

Чтобы просмотреть историю запусков процессов, найдите Start proc .

Определите, зависает ли устройство

Чтобы определить, не зависает ли устройство, проверьте аномальное увеличение активности вокруг am_proc_died и am_proc_start за короткий промежуток времени.

Память

Поскольку устройства Android часто имеют ограниченную физическую память, управление оперативной памятью (ОЗУ) имеет решающее значение. Отчеты об ошибках содержат несколько индикаторов нехватки памяти, а также состояние дампа, обеспечивающее снимок памяти.

Определить нехватку памяти

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

Недостаток памяти также может замедлить переключение задач и помешать попыткам возврата (поскольку задача, к которой пользователь пытался вернуться, была уничтожена). Если программа запуска была отключена, она перезапускается, когда пользователь касается кнопки «Домой», и журналы показывают, что программа запуска перезагружает свое содержимое.

Просмотр исторических показателей

Запись am_low_memory в двоичном журнале событий указывает на то, что последний кэшированный процесс умер. После этого система начинает убивать службы.

Просмотр индикаторов вибрации

Другие индикаторы сбоев системы (подкачка страниц, прямое восстановление и т. д.) включают циклы использования kswapd , kworker и mmcqd . (Имейте в виду, что собираемый отчет об ошибке может повлиять на индикаторы сбоев.)

Журналы ANR могут предоставить аналогичный снимок памяти.

Получить снимок памяти

Снимок памяти — это состояние дампа, в котором перечислены запущенные Java и собственные процессы (подробнее см. в разделе Просмотр общего распределения памяти ). Имейте в виду, что снимок отображает только состояние на определенный момент времени; до моментального снимка система могла быть в лучшем (или худшем) состоянии.

Трансляции

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

Посмотреть исторические трансляции

Исторические передачи — это уже отправленные передачи, перечисленные в обратном хронологическом порядке.

Сводный раздел представляет собой обзор последних 300 передних трансляций и последних 300 фоновых трансляций.

Раздел подробностей содержит полную информацию о последних 50 основных и последних 50 фоновых трансляциях, а также о приемниках каждой трансляции. Ресиверы, имеющие:

  • Запись BroadcastFilter регистрируется во время выполнения и отправляется только уже запущенным процессам.
  • Запись ResolveInfo регистрируется через записи манифеста. ActivityManager запускает процесс для каждого ResolveInfo , если он еще не запущен.

Посмотреть активные трансляции

Активные трансляции — это те, которые еще не отправлены. Большое количество сообщений в очереди означает, что система не может отправлять широковещательные сообщения достаточно быстро, чтобы успевать за ними.

Просмотр слушателей трансляции

Чтобы просмотреть список приемников, прослушивающих широковещательную передачу, проверьте Таблицу разрешения приемников в dumpsys activity broadcasts . В следующем примере показаны все получатели, прослушивающие USER_PRESENT .

Мониторинг конфликтов

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

В системном журнале:

10-01 18:12:44.343 29761 29914 W art     : Long monitor contention event with owner method=void android.database.sqlite.SQLiteClosable.acquireReference() from SQLiteClosable.java:52 waiters=0 for 3.914s

В журнале событий:

10-01 18:12:44.364 29761 29914 I dvm_lock_sample: [com.google.android.youtube,0,pool-3-thread-9,3914,ScheduledTaskMaster.java,138,SQLiteClosable.java,52,100]

Фоновая компиляция

Компиляция может быть дорогостоящей и нагружать устройство.

Компиляция может происходить в фоновом режиме во время загрузки обновлений из магазина Google Play. В этом случае сообщения из приложения магазина Google Play ( finsky ) и installd появляются раньше сообщений dex2oat .

Компиляция также может происходить в фоновом режиме, когда приложение загружает файл dex, который еще не скомпилирован. В этом случае вы не увидите журналы finsky или installd .

Повествование

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

Синхронизировать временные шкалы

Отчет об ошибке отражает несколько параллельных временных шкал: системный журнал, журнал событий, журнал ядра и несколько специализированных временных шкал для широковещательных сообщений, статистики батареи и т. д. К сожалению, временные шкалы часто сообщаются с использованием разных временных баз.

Временные метки системы и журнала событий находятся в том же часовом поясе, что и пользователь (как и большинство других временных меток). Например, когда пользователь нажимает кнопку «Домой», системный журнал сообщает:

10-03 17:19:52.939  1963  2071 I ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.google.android.googlequicksearchbox/com.google.android.launcher.GEL (has extras)} from uid 1000 on display 0

Для того же действия журнал событий сообщает:

10-03 17:19:54.279  1963  2071 I am_focused_activity: [0,com.google.android.googlequicksearchbox/com.google.android.launcher.GEL]

Журналы ядра ( dmesg ) используют другую временную базу, помечая элементы журнала секундами с момента завершения загрузчика. Чтобы зарегистрировать эту временную шкалу в других временных шкалах, найдите сообщения о приостановке выхода и приостановке входа :

<6>[201640.779997] PM: suspend exit 2015-10-03 19:11:06.646094058 UTC
…
<6>[201644.854315] PM: suspend entry 2015-10-03 19:11:10.720416452 UTC

Поскольку журналы ядра могут не включать время в режиме ожидания, вам следует регистрировать журнал по частям между входом в режим ожидания и сообщениями о выходе. Кроме того, журналы ядра используют часовой пояс UTC и должны быть скорректированы с часовым поясом пользователя.

Определите время отчета об ошибке

Чтобы определить, когда был получен отчет об ошибке, сначала проверьте системный журнал (Logcat) на dumpstate: begin :

10-03 17:19:54.322 19398 19398 I dumpstate: begin

Затем проверьте временные метки журнала ядра ( dmesg ) на наличие сообщения Starting service 'bugreport' :

<5>[207064.285315] init: Starting service 'bugreport'...

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

Власть

Журнал событий содержит информацию о состоянии питания экрана, где 0 — экран выключен, 1 — экран включен, а 2 — защита клавиатуры отключена.

Отчеты об ошибках также содержат статистику о блокировках пробуждения — механизме, используемом разработчиками приложений, чтобы указать, что их приложению необходимо, чтобы устройство оставалось включенным. (Подробную информацию о блокировке пробуждения см. в разделах PowerManager.WakeLock и Keep CPU on .)

Совокупная статистика длительности блокировки пробуждения отслеживает только время, в течение которого блокировка пробуждения фактически отвечает за поддержание бодрствования устройства, и не включает время с включенным экраном. Кроме того, если одновременно удерживается несколько блокировок пробуждения, время блокировки пробуждения распределяется между этими блокировками пробуждения.

Для получения дополнительной помощи по визуализации состояния питания используйте Battery Historian , инструмент Google с открытым исходным кодом для анализа потребителей батареи с помощью файлов отчетов об ошибках Android.

Пакеты

Раздел DUMP OF SERVICE package содержит версии приложения (и другую полезную информацию).

Процессы

Отчеты об ошибках содержат огромное количество данных о процессах, включая время запуска и остановки, продолжительность выполнения, связанные службы, оценку oom_adj и т. д. Подробную информацию о том, как Android управляет процессами, см. в разделе Процессы и потоки .

Определить время выполнения процесса

Раздел procstats содержит полную статистику о продолжительности работы процессов и связанных с ними служб. Чтобы получить краткую, удобочитаемую сводку, найдите AGGREGATED OVER чтобы просмотреть данные за последние три или 24 часа, затем найдите Summary: чтобы просмотреть список процессов, продолжительность работы этих процессов с различными приоритетами и их оперативную память. использование в формате мин-средний-макс PSS/мин-средний-макс USS.

Причины, по которым процесс запущен

В разделе dumpsys activity processes перечислены все запущенные в данный момент процессы, упорядоченные по показателю oom_adj (Android указывает важность процесса, присваивая ему значение oom_adj , которое может динамически обновляться с помощью ActivityManager). Вывод аналогичен снимку памяти , но включает дополнительную информацию о том, что вызывает запуск процесса. В приведенном ниже примере записи, выделенные жирным шрифтом, указывают, что процесс gms.persistent выполняется с приоритетом vis (видимый), поскольку системный процесс привязан к своему NetworkLocationService .

Сканирование

Выполните следующие действия, чтобы определить приложения, выполняющие чрезмерное сканирование Bluetooth Low Energy (BLE):

  • Найдите сообщения журнала для BluetoothLeScanner :
    $ grep 'BluetoothLeScanner' ~/downloads/bugreport.txt
    07-28 15:55:19.090 24840 24851 D BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
    
  • Найдите PID в сообщениях журнала. В этом примере «24840» и «24851» — это PID (идентификатор процесса) и TID (идентификатор потока).
  • Найдите приложение, связанное с PID:
    PID #24840: ProcessRecord{4fe996a 24840:com.badapp/u0a105}
    

    В этом примере имя пакета — com.badapp .

  • Найдите название пакета в Google Play, чтобы определить ответственное приложение: https://play.google.com/store/apps/details?id=com.badapp .

Примечание . На устройствах под управлением Android 7.0 система собирает данные для сканирования BLE и связывает эти действия с инициирующим приложением. Подробную информацию см. в разделах «Сканирование с низким энергопотреблением (LE)» и «Bluetooth» .