當應用程式的 UI 執行緒無回應超過
此外,Crashlytics 還可協助您找出特定有問題的執行緒。我們會分析 ANR,然後在 Crashlytics 資訊主頁中標記適用的執行緒,提供如何偵錯 ANR 的提示。
本頁的後續章節將說明各 ANR 標記的意義、顯示含有該標記的 ANR 範例,並提供 ANR 偵錯的建議解決方案。
Triggered ANR
若執行緒阻擋時間過長導致觸發 ANR,就會註明這個 Triggered ANR
有問題的執行緒可能是應用程式的執行緒,或是其他無回應的執行緒。不過,標示為 Triggered 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
Root blocking
若任何執行緒阻擋了標示為 Triggered ANR
Root blocking
Root blocking
Triggered ANR
如果任何 Triggered ANR
Root blocking
查看範例
以下是幾個以執行緒狀態為依據的範例:
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 密集的工作。使用 worker 或背景執行緒執行 CPU 密集型工作。
盡量減少主執行緒上耗用大量 I/O 的工作,例如從資料庫載入資料。
Unknown root cause
如果執行緒觸發了 ANR,但 ANR 發生時其程序處於閒置狀態,就會註明 Unknown root cause
查看範例
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。舉例來說,在程式碼中找出應用程式主執行緒忙碌時間超過