Найдите неотвечающую ветку

В этом документе показано, как определить неотвечающий поток в дампе стека ANR. Неотвечающий поток зависит от типа ошибки ANR, как показано в следующей таблице.

Тип ANR Не отвечает нить
Входная отправка Основная тема
Отправка ввода без сфокусированного окна Основная ветка. Этот тип ANR обычно не вызван блокировкой потока.
Радиовещательный приемник (синхронный) Поток, выполняющийся onReceive() . Это основной поток, если с помощью Context.registerReceiver не указан пользовательский обработчик для неосновного потока.
Широковещательный приемник (асинхронный) Проверьте код, чтобы узнать, какой поток или пул потоков отвечает за обработку широковещательной рассылки после вызова goAsync .
Тайм-аут выполнения службы Основная тема
Запуск службы переднего плана Основная тема
Поставщик контента не отвечает Или:
  • Поток связывания, если ошибка ANR вызвана медленным запросом поставщика контента.
  • Основной поток, если ошибка ANR вызвана длительным запуском приложения.
Нет ответа на onStartJob или onStopJob Основная тема

Иногда поток не отвечает из-за основной причины в другом потоке или процессе. Поток может не отвечать из-за ожидания следующего:

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

Распространенные причины не отвечающих тем

Ниже приведены распространенные причины неотвечающих потоков.

Медленный звонок связующего

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

Вы можете решить эту проблему, переместив синхронные вызовы связывателей в фоновые потоки, где это возможно. Если вызов должен произойти в основном потоке, выясните, почему вызов выполняется медленно. Лучший способ сделать это — использовать следы Perfetto.

Найдите в стеках BinderProxy.transactNative или Binderproxy.transact . Это означает, что происходит вызов связующего. После этих двух строк вы можете увидеть вызываемый API связывателя. В следующем примере вызывается IAccessibilityManager.addClient .

main tid=123

...
android.os.BinderProxy.transactNative (Native method)
android.os.BinderProxy.transact (BinderProxy.java:568)
android.view.accessibility.IAccessibilityManager$Stub$Proxy.addClient (IAccessibilityManager.java:599)
...

Множество последовательных вызовов связующего

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

Блокирующий ввод-вывод

Никогда не выполняйте блокировку ввода-вывода в основном потоке. Это антипаттерн.

Конфликт блокировки

Если поток блокируется при получении блокировки, это может привести к ошибке ANR.

В следующем примере показано, что основной поток блокируется при попытке получить блокировку:

main (tid=1) Blocked

Waiting for com.example.android.apps.foo.BarCache (0x07d657b7) held by
ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD
[...]
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:5412)
[...]

Блокирующий поток отправляет HTTP-запрос на загрузку видео:

ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD (tid=110) Waiting

at jdk.internal.misc.Unsafe.park(Native method:0)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:715)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1047)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:230)
at com.example.android.apps.foo.HttpRequest.execute(HttpRequest:136)
at com.example.android.apps.foo$Task$VideoLoadTask.downloadVideoToFile(RequestExecutor:711)
[...]

Дорогая рама

Рендеринг слишком большого количества объектов в одном кадре может привести к тому, что основной поток не будет отвечать на запросы на протяжении всего кадра, например:

  • Рендеринг множества ненужных закадровых элементов.
  • Использование неэффективного алгоритма, такого как O(n^2) при рендеринге многих элементов пользовательского интерфейса.

Заблокировано другим компонентом

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

Избегайте выполнения тяжелой работы в основном потоке компонентов приложения. По возможности запускайте приемники вещания в другом потоке.