این سند نشان میدهد که چگونه میتوان رشته بدون پاسخ را در یک Dump پشته ANR شناسایی کرد. همانطور که در جدول زیر نشان داده شده است، رشته بدون پاسخ بر اساس نوع ANR متفاوت است.
نوع ANR | موضوع پاسخگو نیست |
---|---|
ارسال ورودی | موضوع اصلی |
ارسال ورودی بدون پنجره متمرکز | موضوع اصلی. این نوع ANR معمولاً توسط یک رشته مسدود شده ایجاد نمی شود. |
گیرنده پخش (همگام) | موضوع در حال اجرا onReceive() . این رشته اصلی است مگر اینکه یک کنترل کننده سفارشی در یک رشته غیر اصلی با استفاده از Context.registerReceiver مشخص شده باشد. |
گیرنده پخش (ناهمزمان) | کد را بررسی کنید تا ببینید کدام رشته یا Thread Pool مسئول انجام کار پردازش پخش پس از فراخوانی goAsync است. |
در حال اجرای سرویس | موضوع اصلی |
شروع خدمات پیش زمینه | موضوع اصلی |
ارائه دهنده محتوا پاسخ نمی دهد | یا:
|
بدون پاسخ به onStartJob یا onStopJob | موضوع اصلی |
گاهی اوقات موضوع به دلیل یک علت ریشه ای در یک رشته یا فرآیند دیگر پاسخ نمی دهد. موضوع ممکن است به دلیل انتظار در موارد زیر پاسخگو نباشد:
- قفلی که توسط نخ دیگری نگه داشته شده است.
- یک کلاسور آهسته به یک فرآیند متفاوت فراخوانی می کند.
علل متداول عدم پاسخگویی موضوعات
موارد زیر دلایل رایج عدم پاسخگویی رشته ها هستند.
تماس آهسته کلاسور
اگرچه بیشتر تماس های کلاسور سریع هستند، دم بلند می تواند بسیار کند باشد. اگر دستگاه بارگیری شود یا رشته پاسخ بایندر کند باشد، مانند بحث قفل، بسیاری از تماسهای کلاسور ورودی، یا مهلت زمانی لایه انتزاع سختافزاری (HAL) این اتفاق بیشتر میافتد.
میتوانید این مشکل را با انتقال تماسهای کلاسور همزمان به رشتههای پسزمینه تا جایی که ممکن است حل کنید. اگر تماس باید در رشته اصلی اتفاق بیفتد، علت کندی تماس را دریابید. بهترین راه برای انجام این کار از Perfetto Traces است.
به دنبال BinderProxy.transactNative
یا Binderproxy.transact
در پشته ها بگردید. این به این معنی است که تماس بایندر در حال انجام است. با دنبال کردن این دو خط، می توانید API بایندر را مشاهده کنید که فراخوانی شده است. در مثال زیر، تماس با IAccessibilityManager.addClient
است.
main tid=123
...
android.os.BinderProxy.transactNative (Native method)
android.os.BinderProxy.transact (BinderProxy.java:568)
android.view.accessibility.IAccessibilityManager$Stub$Proxy.addClient (IAccessibilityManager.java:599)
...
بسیاری از تماس های متوالی کلاسور
انجام بسیاری از تماس های متوالی بایندر در یک حلقه محکم می تواند یک نخ را برای مدت طولانی مسدود کند.
ورودی/خروجی مسدودکننده
هرگز مسدود کردن ورودی/خروجی را روی رشته اصلی انجام ندهید. این یک ضد الگو است.
قفل جدال
اگر یک رشته هنگام به دست آوردن قفل مسدود شود، می تواند منجر به ANR شود.
مثال زیر نشان می دهد که موضوع اصلی هنگام تلاش برای به دست آوردن قفل مسدود شده است:
main (tid=1) Blocked
Waiting for com.example.android.apps.foo.BarCache (0x07d657b7) held by
ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD
[...]
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:5412)
[...]
رشته مسدود کننده درخواست HTTP برای دانلود یک ویدیو می کند:
ptz-rcs-28-EDITOR_REMOTE_VIDEO_DOWNLOAD (tid=110) Waiting
at jdk.internal.misc.Unsafe.park(Native method:0)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:715)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1047)
at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:230)
at com.example.android.apps.foo.HttpRequest.execute(HttpRequest:136)
at com.example.android.apps.foo$Task$VideoLoadTask.downloadVideoToFile(RequestExecutor:711)
[...]
قاب گران قیمت
رندر کردن بیش از حد موارد در یک فریم می تواند باعث شود که نخ اصلی در طول مدت فریم پاسخگو نباشد، مانند موارد زیر:
- رندر کردن بسیاری از موارد غیر ضروری خارج از صفحه.
- استفاده از یک الگوریتم ناکارآمد، مانند
O(n^2)
، هنگام رندر کردن بسیاری از عناصر UI.
توسط مؤلفه دیگر مسدود شده است
اگر مؤلفه دیگری مانند گیرنده پخش، رشته اصلی را برای بیش از پنج ثانیه مسدود کند، میتواند باعث ANRهای ارسال ورودی و jank جدی شود.
از انجام هرگونه کار سنگین روی رشته اصلی در اجزای برنامه خودداری کنید. هر جا که ممکن است گیرنده های پخش را روی یک رشته متفاوت اجرا کنید.