当应用的界面线程在 5 秒内没有响应时,便会触发应用无响应 (ANR) 错误。您可以查看 Android 文档详细了解 ANR 以及如何诊断 ANR。
此外,Crashlytics 还有助于查明有问题的具体线程。我们会分析 ANR,然后在 Crashlytics 信息中心中标记相应的线程,以便提供有关如何调试 ANR 的提示。
本页面的以下部分介绍了每个 ANR 标记的含义,展示了带有该标记的示例 ANR,并提供了调试 ANR 的建议解决方案。
Triggered ANR
被阻止的时间过长并触发 ANR 的线程会被添加此 Triggered ANR
标记。
存在问题的线程可以是应用的主线程,也可以是被发现无响应的任何线程。不过,标记为 Triggered ANR
的线程不一定是导致 ANR 的原因。为了提供调试和解决这些 ANR 问题的数据分析,Crashlytics 还会标记 ANR 所涉及的任何其他线程。在本页面的以下部分中,您将了解可应用于线程的其他标记。
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 )
建议
一般来说,您的应用不应对主线程执行昂贵的 I/O 操作。如果主线程为 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 )
建议
最大限度地减少主线程中的 CPU 密集型工作。使用工作器线程或后台线程执行 CPU 密集型任务。
最大限度地减少主线程中的 I/O 密集型工作,例如从数据库加载数据。
Unknown root cause
如果某个线程触发了 ANR,但在 ANR 发生时处于空闲状态,则系统会使用 Unknown root cause
标记来标记该线程。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 秒的位置。