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