ข้อผิดพลาด "แอปพลิเคชันไม่ตอบสนอง" (ANR) จะแสดงขึ้นเมื่อเธรด UI ของแอปพลิเคชันไม่ตอบสนองนานกว่า 5 วินาที คุณสามารถอ่านข้อมูลเพิ่มเติมเกี่ยวกับ ANR และการวินิจฉัย ANR ได้ในเอกสารประกอบของ Android
นอกจากนี้ Crashlytics ยังช่วยระบุชุดข้อความที่มีปัญหาได้ เราจะวิเคราะห์ ANR จากนั้นในหน้าแดชบอร์ด Crashlytics เราจะติดแท็กชุดข้อความที่เกี่ยวข้องเพื่อให้คำแนะนำเกี่ยวกับวิธีแก้ไขข้อบกพร่อง ANR
ส่วนต่อไปนี้ในหน้านี้จะอธิบายความหมายของแท็ก ANR แต่ละรายการ แสดงตัวอย่าง ANR ที่มีแท็กนั้น และระบุวิธีแก้ปัญหาที่แนะนําในการแก้ไขข้อบกพร่อง ANR
Triggered ANR
เทรดที่ถูกบล็อกนานเกินไปและเรียกให้เกิด ANR จะมีคำอธิบายประกอบด้วยแท็ก Triggered ANR
นี้
ชุดข้อความที่เป็นปัญหาอาจเป็นชุดข้อความหลักของแอป หรือชุดข้อความใดก็ตามที่พบว่าไม่ตอบสนอง อย่างไรก็ตาม เทรดที่ติดแท็กเป็น Triggered ANR
อาจไม่ใช่สาเหตุจริงของ ANR Crashlytics จะติดแท็กเทรดอื่นๆ ที่เกี่ยวข้องกับ ANR ด้วย เพื่อให้ข้อมูลเชิงลึกสำหรับการแก้ไขข้อบกพร่องและแก้ไข ANR เหล่านี้ ดูข้อมูลเกี่ยวกับแท็กอื่นๆ ที่อาจใช้กับชุดข้อความได้ในส่วนต่อไปนี้ของหน้านี้
Deadlocked
เทรดใดก็ตามที่พบว่าเกี่ยวข้องกับการติดตายที่ทำให้เกิด ANR จะมีคำอธิบายประกอบด้วยแท็ก Deadlocked
นี้
การล็อกคิวเกิดขึ้นเมื่อเธรดเข้าสู่สถานะรอเนื่องจากเธรดอื่นถือทรัพยากรที่จําเป็นอยู่ ซึ่งก็รอทรัพยากรที่เธรดแรกถืออยู่ด้วย หากเทรดหลักของแอปอยู่ในสถานการณ์เช่นนี้ ก็มีโอกาสที่จะเกิด ANR
ดูตัวอย่าง
เทรด 2 รายการที่เกี่ยวข้องกับการติดตายมีดังนี้
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)
คำแนะนำ
ดูที่ชุดข้อความที่เกี่ยวข้องกับการล็อกตายและตรวจสอบทรัพยากร/ล็อกที่ชุดข้อความเหล่านั้นได้รับ โปรดดูวิธีแก้ปัญหาที่เป็นไปได้จากหัวข้อDeadlock และDeadlock prevention algorithms
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
เทรดจะติดแท็ก Unknown root cause
หากเป็นเทรดที่เรียกให้เกิด ANR แต่ไม่ได้ทำงานในกระบวนการเมื่อเกิด 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 วินาที