Lỗi Ứng dụng không phản hồi (ANR) được kích hoạt khi luồng giao diện người dùng của
ứng dụng không phản hồi trong hơn 5 giây. Bạn có thể đọc
thêm về lỗi ANR và cách chẩn đoán lỗi ANR trong
tài liệu Android.
Ngoài ra, Crashlytics có thể giúp xác định các luồng cụ thể có vấn đề. Chúng tôi
phân tích lỗi ANR, sau đó, trong trang tổng quan Crashlytics, chúng tôi
gắn thẻ các luồng áp dụng để đưa ra gợi ý về cách gỡ lỗi ANR.
Các phần sau đây trên trang này giải thích ý nghĩa của từng thẻ ANR, cho thấy ví dụ về lỗi ANR có thẻ đó và đưa ra giải pháp được đề xuất để gỡ lỗi ANR.
Triggered ANR
Một luồng đã bị chặn quá lâu và kích hoạt ANR sẽ được chú thích bằng
thẻ Triggered ANR này.
Luồng có vấn đề có thể là luồng chính của ứng dụng hoặc bất kỳ luồng nào được phát hiện là không phản hồi. Tuy nhiên, luồng được gắn thẻ là
Triggered ANR có thể là hoặc không phải là nguyên nhân thực sự gây ra
ANR. Để cung cấp thông tin chi tiết cho việc gỡ lỗi và khắc phục các lỗi ANR này,
Crashlytics cũng gắn thẻ mọi luồng khác có liên quan đến lỗi ANR. Trong các phần sau của trang này, hãy tìm hiểu về các thẻ khác có thể được áp dụng cho một luồng.
Deadlocked
Mọi luồng được phát hiện có liên quan đến tình trạng tắc nghẽn dẫn đến lỗi ANR đều được
chú thích bằng thẻ Deadlocked này.
Tình trạng tắc nghẽn sẽ xảy ra khi một luồng chuyển sang trạng thái chờ vì một tài nguyên cần thiết được giữ lại trong một luồng khác, đồng thời đang chờ tài nguyên do luồng đầu tiên lưu giữ. Nếu luồng chính của ứng dụng rơi vào trường hợp này, thì nhiều khả năng lỗi ANR sẽ xảy ra.
Xem ví dụ
Dưới đây là 2 luồng liên quan đến tình trạng tắc nghẽn:
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)
Đề xuất
Xem các luồng liên quan đến tình trạng tắc nghẽn và kiểm tra các tài nguyên/khoá do các luồng đó thu được. Tham khảo bài viết về
Thuật toán tắc nghẽn và
Thuật toán ngăn ngừa tắc nghẽn
để biết các giải pháp có thể.
IO Root blocking
Bất kỳ luồng nào đang thực thi các thao tác nhập/xuất (I/O) chậm và đã chặn luồng
Triggered ANR đều được chú thích bằng thẻ
IO Root blocking. Nếu luồng
Triggered ANR không bị các luồng khác chặn,
thì luồng IO Root blocking cũng là luồng
Root blocking.
Xem ví dụ
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 )
Đề xuất
Nhìn chung, ứng dụng của bạn không nên thực thi các thao tác I/O tốn kém trên luồng chính. Trong trường hợp luồng chính là
IO Root blocking, bạn cũng có thể sử dụng
Chế độ nghiêm ngặt
để xác định mọi thao tác I/O không chủ ý đang diễn ra trên luồng chính.
Root blocking
Bất kỳ luồng nào đã chặn luồng được gắn thẻ là
Triggered ANR đều được chú thích bằng thẻ
Root blocking. Nếu một luồng được gắn thẻ là cả
Root blocking và
Triggered ANR, thì không có luồng nào khác
chặn luồng đó.
Nếu bất kỳ Triggered ANR luồng nào đang chờ (có thể
gián tiếp) các luồng khác, thì đó là
Root blocking. Có thể có nhiều lý do khiến một luồng là nguyên nhân gốc gây ra lỗi ANR.
Xem ví dụ
Dưới đây là một vài ví dụ dựa trên trạng thái luồng:
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 )
Đề xuất
Giảm thiểu công việc tiêu tốn nhiều CPU trong luồng chính. Sử dụng luồng trình thực thi hoặc luồng ở chế độ nền để thực hiện các tác vụ tiêu tốn nhiều CPU.
Giảm thiểu công việc tiêu tốn nhiều I/O, chẳng hạn như tải từ cơ sở dữ liệu, trên luồng chính.
Unknown root cause
Một luồng được gắn thẻ bằng thẻ Unknown root cause nếu
đó là luồng đã kích hoạt ANR nhưng không hoạt động trong quá trình khi
ANR xảy ra. Crashlytics không có đủ thông tin để xác định
nguyên nhân gốc. Không có bằng chứng về lý do khiến ANR này xảy ra.
Xem ví dụ
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 )
Đề xuất
Làm theo lời khuyên chung về cách ngăn chặn lỗi ANR. Ví dụ: xác định các
vị trí trong mã của bạn nơi luồng chính của ứng dụng có thể bận trong hơn
5 giây.