Gỡ lỗi ứng dụng Android dựa trên thẻ ANR trong trang tổng quan Crashlytics
Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
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 của Android.
Ngoài ra, Crashlytics có thể giúp xác định chính xác các luồng có vấn đề cụ thể. Chúng tôi phân tích các lỗi ANR, sau đó trong trang tổng quan Crashlytics, chúng tôi gắn thẻ các luồng có thể á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 một ví dụ về lỗi ANR có thẻ đó và cung cấp 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 lỗi 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ề những thẻ khác có thể được áp dụng cho một chuỗi.
Deadlocked
Mọi luồng được phát hiện có liên quan đến một tình trạng bế tắc dẫn đến 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ụ
Sau đây là 2 luồng liên quan đến một bế tắc:
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 xét các luồng liên quan đến tình trạng bế tắc và kiểm tra các tài nguyên/khoá mà các luồng đó đã có được. Hãy tham khảo bài viết về 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ể áp dụng.
IO Root blocking
Mọi luồng đang thực thi các thao tác 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 tiêu tốn nhiều tài nguyên 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
Mọi luồng đã 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 có bất kỳ luồng Triggered ANR
nào đang chờ (có thể là gián tiếp) các luồng khác, thì các luồng đó sẽ Root blocking
. Có nhiều lý do khiến một luồng là nguyên nhân gốc của lỗi ANR.
Xem ví dụ
Sau đây là một số ví dụ dựa trên trạng thái của 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 sử dụng nhiều CPU trong luồng chính. Sử dụng worker hoặc luồng nền để thực hiện các tác vụ sử dụng nhiều CPU.
Giảm thiểu thao tác I/O chuyên sâu (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ẻ 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 những vị trí trong mã của bạn mà luồng chính của ứng dụng có thể bận trong hơn 5 giây.