خطاهای عدم پاسخگویی برنامه (ANR) زمانی رخ میدهند که رابط کاربری (UI thread) برنامه بیش از 5 ثانیه پاسخ ندهد. میتوانید اطلاعات بیشتر در مورد ANRها و تشخیص ANRها را در مستندات اندروید مطالعه کنید.
علاوه بر این، Crashlytics میتواند به شناسایی دقیق رشتههای مشکلساز خاص کمک کند. ما ANRها را تجزیه و تحلیل میکنیم و سپس، در داشبورد Crashlytics ، رشتههای مربوطه را برچسبگذاری میکنیم تا نکاتی در مورد نحوه اشکالزدایی ANR ارائه دهیم.
بخشهای بعدی این صفحه توضیح میدهند که هر برچسب ANR به چه معناست، یک نمونه ANR با آن برچسب را نشان میدهد و یک راه حل پیشنهادی برای اشکالزدایی ANR ارائه میدهد.
Triggered ANR
یک رشته که برای مدت طولانی مسدود شده و باعث ایجاد ANR شده است، با این علامتگذاری میشود. برچسب Triggered ANR .
تاپیک مشکلدار میتواند تاپیک اصلی برنامه یا هر تاپیکی باشد که پاسخگو نباشد. با این حال، تاپیک با برچسب Triggered ANR ممکن است علت اصلی ANR باشد یا نباشد. برای ارائه بینشهایی برای اشکالزدایی و رفع این ANRها، Crashlytics سایر رشتههایی را که در ANR دخیل هستند نیز برچسبگذاری میکند. در بخشهای بعدی این صفحه، درباره سایر برچسبهایی که میتوانند برای یک رشته اعمال شوند، اطلاعات کسب کنید.
Deadlocked
هر رشتهای که مشخص شود در بنبستی که منجر به ANR شده است، دخیل بوده است، با این حاشیهنویسی میشود تگ Deadlocked .
بنبست زمانی رخ میدهد که یک نخ به دلیل در اختیار داشتن منبع مورد نیاز توسط نخ دیگری که آن هم منتظر منبعی است که توسط نخ اول در اختیار دارد، وارد حالت انتظار شود. اگر نخ اصلی برنامه در این وضعیت باشد، احتمال وقوع 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
هر نخی که عملیات ورودی/خروجی کندی را اجرا میکرد و آن را مسدود میکرد رشته 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 )
توصیه
به طور کلی، برنامه شما نباید عملیات ورودی/خروجی پرهزینه را روی نخ اصلی اجرا کند. در صورتی که نخ اصلی ... IO Root blocking )، همچنین میتوانید از حالت سختگیرانه (Strict Mode) برای شناسایی هرگونه عملیات ورودی/خروجی ناخواسته که در نخ اصلی اتفاق میافتد، استفاده کنید.
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 در نخ اصلی را به حداقل برسانید. از نخهای کارگر یا پسزمینه برای انجام وظایف فشرده CPU استفاده کنید.
کارهای فشرده ورودی/خروجی، مانند بارگذاری از پایگاه داده، را در نخ اصلی به حداقل برسانید.
Unknown root cause
یک تاپیک با برچسب اگر این رشته باعث ایجاد ANR شده باشد اما در حین فرآیند هنگام وقوع ANR غیرفعال بوده باشد، برچسب Unknown root cause . 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ها را دنبال کنید. برای مثال، مکانهایی را در کد خود شناسایی کنید که در آنها رشته اصلی برنامه میتواند بیش از ۵ ثانیه مشغول باشد.