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