Ошибки ANR ("Приложение не отвечает") возникают, когда поток UI приложения не отвечает более 5 секунд. Подробную информацию об ошибках ANR и их диагностике можно найти в документации Android.
Кроме того, Crashlytics может помочь выявить конкретные проблемные цепочки. Мы анализируем ошибки ANR и на панели DevOps и вовлеченность > Crashlytics помечаем тегами соответствующие потоки, чтобы дать подсказки по отладке.
В следующих разделах этой страницы объясняется, что означает каждый тег ANR, приводится пример ANR с этим тегом и предлагается рекомендуемое решение для отладки ANR.
Triggered ANR
Поток, который был заблокирован слишком долго и вызвал ошибку ANR, помечается тегом Triggered ANR.
Проблемным может быть основной поток приложения или любой другой поток, который не отвечает. Однако поток, помеченный как Triggered ANR, может и не быть фактической причиной ошибки ANR. Чтобы помочь вам в отладке и устранении ошибок ANR, Crashlytics также помечает другие потоки, связанные с ошибкой. В следующих разделах этой страницы вы узнаете о других тегах, которые могут быть применены к цепочке.
Deadlocked
Все потоки, которые участвовали во взаимной блокировке, приведшей к ошибке ANR, помечаются тегом Deadlocked.
Взаимная блокировка возникает, когда поток переходит в режим ожидания, потому что необходимый ресурс занят другим потоком, который также ожидает ресурс, занятый первым потоком. Если в такой ситуации оказывается основной поток приложения, скорее всего, возникнет ошибка ANR.
Посмотреть пример
Вот два потока, участвующих во взаимной блокировке:
main (unknown): tid=1 systid=1568
com.android.server.pm.PackageManagerService$PackageManagerInternalImpl.getPackage(PackageManagerService.java:22701)
com.android.server.pm.PackageManagerService$PackageManagerInternalImpl.filterOnlySystemPackages(PackageManagerService.java:22787)
...
com.android.server.SystemServer.main(SystemServer.java:368)
java.lang.reflect.Method.invoke(Native method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:517)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
ActivityManager (unknown): tid=21 systid=1902
com.android.server.pm.PackageManagerService.getPackageSetting(PackageManagerService.java:23618)
com.android.server.pm.PackageManagerService.getPackageUid(PackageManagerService.java:4542)
...
android.os.Handler.handleCallback(Handler.java:907)
android.os.Handler.dispatchMessage(Handler.java:99)
android.os.Looper.loop(Looper.java:216)
android.os.HandlerThread.run(HandlerThread.java:67)
com.android.server.ServiceThread.run(ServiceThread.java:44)
Рекомендация
Посмотрите на потоки, участвующие во взаимной блокировке, и проверьте ресурсы/блокировки, полученные этими потоками. Возможные решения описаны в статьях Взаимная блокировка и Алгоритмы предотвращения взаимной блокировки.
IO Root blocking
Любой поток, который выполнял медленные операции I/O и блокировал поток Triggered ANR, помечается тегом IO Root blocking. Если поток Triggered ANR не заблокирован другими потоками, то поток IO Root blocking также является потоком Root blocking.
Посмотреть примеры
Thread main(THREAD_STATE_TIMED_WAITING)
sun.misc.Unsafe.park( Unsafe.java:0 )
java.util.concurrent.locks.LockSupport.parkNanos( LockSupport.java:230 )
android.database.sqlite.SQLiteConnectionPool.waitForConnection( SQLiteConnectionPool.java:756 )
...
android.app.ActivityThread.main( ActivityThread.java:8192 )
Thread main(THREAD_STATE_NATIVE_WAITING)
Syscall
art::ConditionVariable::WaitHoldingLocks(art::Thread*)
art::GoToRunnable(art::Thread*)
art::JniMethodEnd(unsigned int, art::Thread*)
libcore.io.Linux.fdatasync( Linux.java:0 )
libcore.io.ForwardingOs.fdatasync( ForwardingOs.java:105 )
...
java.io.RandomAccessFile.write( RandomAccessFile.java:559 )
...
android.app.ActivityThread.main( ActivityThread.java:8192 )
Рекомендация
В целом не рекомендуется выполнять ресурсоемкие операции ввода-вывода в основном потоке. Если основной поток IO Root blocking, вы также можете использовать строгий режим, чтобы выявить непреднамеренные операции I/O, которые выполняются в основном потоке.
Root blocking
Любой поток, который заблокировал поток с тегом Triggered ANR, помечается тегом Root blocking. Если цепочка помечена как Root blocking и Triggered ANR, то нет других цепочек, которые ее блокируют.
Если какие-либо потоки Triggered ANR ожидали (возможно, транзитивно) другие потоки, они Root blocking. Причины, по которым поток может быть основной причиной ошибки ANR, могут быть разными.
Посмотреть примеры
Вот несколько примеров в зависимости от состояния цепочки:
Thread main(THREAD_STATE_RUNNABLE)
android.os.Parcel.createTypedArray( Parcel.java:3086 )
android.content.pm.PackageInfo.<init>( PackageInfo.java:546 )
...
android.app.ActivityThread$H.handleMessage( ActivityThread.java:2166 )
android.os.Handler.dispatchMessage( Handler.java:106 )
android.os.Looper.loop( Looper.java:246 )
android.app.ActivityThread.main( ActivityThread.java:8633 )
Thread main(THREAD_STATE_BLOCKED)
DBHelper.runOnDB( DBHelper.java:97 )
DBHelper.runDb( DBHelper.java:125 )
...
java.lang.reflect.Method.invoke( Method.java:0 )
EventBus.invokeSubscriber( EventBus.java:510 )
postToSubscription( EventBus.java:437 )
...
android.os.Handler.handleCallback( Handler.java:938 )
android.os.Handler.dispatchMessage( Handler.java:99 )
android.os.Looper.loop( Looper.java:268 )
android.app.ActivityThread.main( ActivityThread.java:7904 )
Рекомендация
Минимизируйте работу, требующую высокой производительности ЦП, в основном потоке. Для выполнения задач, требующих интенсивного использования ЦП, используйте рабочие или фоновые потоки.
Минимизируйте в основном потоке работу, связанную с I/O, например загрузку из базы данных.
Unknown root cause
Тег Unknown root cause присваивается потоку, который вызвал ошибку ANR, но бездействовал в процессе, когда она произошла. У Crashlytics недостаточно информации, чтобы определить основную причину. Очевидной причины возникновения этой ошибки ANR нет.
Посмотреть пример
Thread main(THREAD_STATE_NATIVE_WAITING) __epoll_pwait
android::Looper::pollInner(int)
android::Looper::pollOnce(int, int*, int*, void**)
android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)
android.os.MessageQueue.nativePollOnce( MessageQueue.java:0 )
android.os.MessageQueue.next( MessageQueue.java:335 )
android.os.Looper.loop( Looper.java:193 )
android.app.ActivityThread.main( ActivityThread.java:8019 )
Рекомендация
Следуйте общим рекомендациям по предотвращению ошибок ANR. Например, определите, в каких местах кода основной поток приложения может быть занят более 5 секунд.
Waiting for binder call
Любой поток, который ожидал вызова связывателя и заблокировал поток Triggered ANR, помечается тегом Waiting for binder call. Если поток Triggered ANR не заблокирован другими потоками, то поток Waiting for binder call также является потоком Root blocking.
Посмотреть пример
Thread main(THREAD_STATE_NATIVE_WAITING)
syscall
android::IPCThreadState::talkWithDriver(bool)
android::IPCThreadState::waitForResponse(android::Parcel*, int*)
android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)
android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)
android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)
android.os.BinderProxy.transactNative( BinderProxy.java:0 )
android.os.BinderProxy.transact( BinderProxy.java:540 )
android.app.IActivityManager$Stub$Proxy.getContentProvider( IActivityManager.java:5945 )
android.app.ActivityThread.acquireProvider( ActivityThread.java:7138 )
android.app.ActivityThread$H.handleMessage( ActivityThread.java:1982 )
android.os.Handler.dispatchMessage( Handler.java:106 )
android.os.Looper.loop( Looper.java:236 )
android.app.ActivityThread.main( ActivityThread.java:8037 )
Рекомендация
Поскольку задержка вызова binder может быть непредсказуемой, относитесь к таким вызовам как к операциям I/O и по возможности избегайте их в основном потоке. Переместите код, который запускает вызовы Binder (включая вызовы API платформы, приводящие к транзакциям Binder), в фоновый поток или кешируйте результаты, если вызов из основного потока неизбежен.