تصحيح أخطاء تطبيق Android استنادًا إلى علامات ANR في لوحة بيانات Crashlytics
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
يتم تفعيل أخطاء "التطبيق لا يستجيب" (ANR) عندما لا تستجيب سلسلة واجهة المستخدم في التطبيق لمدة تزيد عن 5 ثوانٍ. يمكنك الاطّلاع على مزيد من المعلومات حول أخطاء ANR وتشخيصها في مستندات Android.
بالإضافة إلى ذلك، يمكن أن تساعد Crashlytics في تحديد المشاكل المحدّدة في سلاسل التعليمات البرمجية. نحلّل أخطاء ANR، ثم نضع علامات على سلاسل التعليمات البرمجية ذات الصلة في لوحة بيانات Crashlytics لتقديم تلميحات حول كيفية تصحيح خطأ ANR.
توضّح الأقسام التالية في هذه الصفحة معنى كل علامة ANR، وتعرض مثالاً على خطأ ANR مع تلك العلامة، وتقدّم حلاً مقترحًا لتصحيح خطأ ANR.
Triggered ANR
يتم وضع العلامة Triggered ANR
على سلسلة التعليمات التي تم حظرها لفترة طويلة جدًا وتسبّبت في حدوث خطأ ANR.
يمكن أن تكون سلسلة المحادثات التي تتضمّن مشاكل هي سلسلة المحادثات الرئيسية للتطبيق، أو أي سلسلة محادثات أخرى تبيّن أنّها لا تستجيب. ومع ذلك، قد يكون مؤشر الترابط الذي تم وضع علامة Triggered ANR
عليه هو السبب الفعلي في حدوث خطأ ANR أو لا يكون هو السبب. لتقديم إحصاءات لتصحيح أخطاء ANR وإصلاحها،
تعمل Crashlytics أيضًا على وضع علامات على أي سلاسل محادثات أخرى متورّطة في خطأ ANR. في الأقسام التالية من هذه الصفحة، يمكنك التعرّف على العلامات الأخرى التي يمكن تطبيقها على سلسلة محادثات.
Deadlocked
تتم إضافة التعليق التوضيحي الذي يتضمّن العلامة Deadlocked
إلى أي سلاسل محادثات تم رصدها على أنّها متورّطة في حالة توقّف تام أدّت إلى حدوث خطأ ANR.
يحدث التوقف التام عندما تدخل سلسلة تعليمات في حالة انتظار لأنّ سلسلة تعليمات أخرى تحتفظ بمورد مطلوب، وتنتظر هذه السلسلة أيضًا موردًا تحتفظ به سلسلة التعليمات الأولى. إذا كانت سلسلة التعليمات الرئيسية للتطبيق في هذا الموقف، من المحتمل حدوث أخطاء 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
يتم وضع التعليق التوضيحي IO Root blocking
على أي سلسلة تعليمات كانت تنفّذ عمليات بطيئة متعلقة بوحدات الإدخال والإخراج وحظرت سلسلة التعليمات Triggered ANR
. إذا لم يتم حظر سلسلة التعليمات
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 )
الاقتراح
بشكل عام، يجب ألا ينفّذ تطبيقك عمليات إدخال/إخراج مكلفة في سلسلة التعليمات الرئيسية. في حال كانت السلسلة الرئيسية IO Root blocking
، يمكنك أيضًا استخدام وضع Strict Mode لتحديد أي عمليات إدخال/إخراج غير مقصودة تحدث في السلسلة الرئيسية.
Root blocking
يتم وضع التعليق التوضيحي Root blocking
على أي سلسلة محادثات حظرت سلسلة المحادثات التي تم وضع العلامة Triggered ANR
عليها. إذا تم تصنيف سلسلة محادثات على أنّها
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 )
الاقتراح
تقليل العمل المكثّف لوحدة المعالجة المركزية في سلسلة التعليمات الرئيسية استخدِم سلاسل العامل أو سلاسل الخلفية لتنفيذ المهام التي تتطلّب استخدامًا مكثّفًا لوحدة المعالجة المركزية.
تقليل العمليات المكثّفة لوحدات الإدخال والإخراج، مثل التحميل من قاعدة بيانات، في سلسلة التعليمات الرئيسية
Unknown root cause
يتم وضع العلامة Unknown root cause
على سلسلة التعليمات البرمجية إذا كانت هي التي تسبّبت في حدوث خطأ 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 ثوانٍ.