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

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

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

Logcat

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

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

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

К уровням логирования относятся следующие:

  • V: многословный
  • D: отладка
  • I: информация
  • W: предупреждение
  • E: ошибка

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

ANR и тупики

Bugreports поможет вам определить причины ошибок "Приложение не отвечает" (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 (Anti-Records — ошибки, связанные с некорректным отображением), поскольку потоки зависают. Если взаимоблокировка затрагивает системный сервер, сторожевой таймер в конечном итоге завершает её, что приводит к записи в журнале, подобной: WATCHDOG KILLING SYSTEM PROCESS . С точки зрения пользователя, устройство перезагружается, хотя технически это перезапуск во время выполнения, а не настоящая перезагрузка.

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

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

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

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

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

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

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

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

Определите, не работает ли устройство с перебоями.

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

Память

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

Выявление низкого уровня памяти

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

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

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

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

Просмотреть индикаторы тряски

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

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

Сделать снимок памяти

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

Трансляции

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

Просмотреть историю трансляций

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

В разделе «Сводка» представлен обзор последних 300 передач в основной программе и последних 300 передач в фоновом режиме.

В разделе «Подробности» содержится полная информация о последних 50 передачах в фоновом и переднем режимах, а также о приемниках для каждой передачи. Приемники, имеющие:

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

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

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

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

Чтобы просмотреть список приемников, ожидающих широковещательной рассылки, проверьте таблицу Receiver Resolver Table в разделе 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 the CPU on .)

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

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

Пакеты

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

Процессы

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

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

Раздел procstats содержит полную статистику о продолжительности работы процессов и связанных с ними служб. Для быстрого и понятного просмотра сводки выполните поиск по запросу AGGREGATED OVER , чтобы просмотреть данные за последние три или 24 часа, а затем выполните поиск по Summary: чтобы просмотреть список процессов, продолжительность их работы с различными приоритетами и использование оперативной памяти в формате min-average-max PSS/min-average-max 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» .