Jika UI thread aplikasi Android diblokir terlalu lama, sistem akan mengirim error "Aplikasi Tidak Merespons" (ANR). Halaman ini menjelaskan berbagai jenis ANR, cara mendiagnosisnya, dan saran untuk memperbaikinya. Semua rentang waktu tunggu default yang tercantum adalah untuk perangkat AOSP dan Pixel; waktu ini dapat berbeda-beda tergantung OEM.
Perlu diingat bahwa saat menentukan penyebab ANR, sebaiknya bedakan antara masalah sistem dan aplikasi.
Saat sistem dalam kondisi buruk, masalah berikut dapat menyebabkan ANR:
- Masalah sementara di server sistem biasanya menyebabkan panggilan binder cepat menjadi lambat.
- Masalah pada server sistem dan beban perangkat yang tinggi menyebabkan thread aplikasi tidak dijadwalkan.
Jika tersedia, cara yang baik untuk membedakan antara masalah sistem dan aplikasi adalah dengan menggunakan rekaman aktivitas Perfetto:
- Lihat apakah thread utama aplikasi terjadwal dengan melihat catatan status thread di Perfetto untuk melihat apakah thread utama sedang berjalan atau dapat dijalankan.
- Lihat thread
system_server
untuk menemukan masalah seperti pertentangan kunci. - Untuk panggilan binder lambat, lihat thread balasan jika ada, untuk melihat penyebab panggilan binder lambat.
Waktu tunggu pengiriman input habis
ANR pengiriman input terjadi saat thread utama aplikasi tidak merespons peristiwa input, seperti geser atau penekanan tombol, secara tepat waktu. Karena aplikasi berada di latar depan saat waktu tunggu pengiriman input habis, aplikasi hampir selalu terlihat oleh pengguna dan sangat penting untuk dimitigasi.
Periode waktu tunggu default: 5 detik.
ANR pengiriman input biasanya disebabkan oleh masalah di thread utama. Jika thread utama diblokir saat menunggu untuk mendapatkan kunci, thread holder juga dapat dilibatkan.
Untuk menghindari ANR pengiriman input, ikuti praktik terbaik berikut:
- Jangan menjalankan operasi pemblokiran atau yang berjalan lama di thread utama. Sebaiknya
gunakan
StrictMode
untuk menangkap aktivitas yang tidak disengaja di thread utama. - Minimalkan pertentangan kunci antara thread utama dan thread lainnya.
- Minimalkan pekerjaan non-UI di thread utama, seperti saat menangani siaran atau menjalankan layanan.
Penyebab umum
Berikut beberapa penyebab umum dan perbaikan yang disarankan untuk ANR pengiriman input.
Penyebab | Yang terjadi | Saran perbaikan |
---|---|---|
Panggilan binder lambat | Thread utama melakukan panggilan binder sinkron yang panjang. | Pindahkan panggilan dari thread utama atau coba optimalkan panggilan, jika Anda adalah pemilik API. |
Banyak panggilan binder berturut-turut | Thread utama melakukan banyak panggilan binder sinkron berturut-turut. | Jangan melakukan panggilan binder dalam loop yang padat. |
I/O pemblokir | Thread utama melakukan panggilan I/O pemblokir, seperti akses database atau jaringan. | Pindahkan semua IO pemblokir dari thread utama. |
Pertentangan kunci | Thread utama diblokir saat menunggu untuk mendapatkan kunci. | Kurangi pertentangan kunci antara thread utama dan thread lainnya. Optimalkan kode lambat di thread lainnya. |
Frame mahal | Rendering terlalu banyak dalam satu frame, sehingga menyebabkan jank yang parah. | Lakukan lebih sedikit pekerjaan yang merender frame. Jangan gunakan algoritma n2. Gunakan komponen yang efisien untuk hal-hal seperti men-scroll atau melakukan paging—misalnya, library Paging Jetpack. |
Diblokir oleh komponen lain | Komponen lain, seperti penerima siaran, sedang berjalan dan memblokir thread utama. | Pindahkan tugas non-UI dari thread utama sebanyak mungkin. Jalankan penerima siaran di thread lain. |
Hang GPU | Hang GPU adalah masalah sistem atau hardware yang menyebabkan rendering diblokir, sehingga terjadilah ANR pengiriman input. | Sayangnya, biasanya tidak ada perbaikan di sisi aplikasi. Jika memungkinkan, hubungi tim hardware untuk memecahkan masalah. |
Cara men-debug
Mulai proses debug dengan melihat tanda tangan cluster ANR di Konsol Google Play atau Firebase Crashlytics. Cluster biasanya berisi frame teratas yang diduga menyebabkan ANR.
Diagram alur berikut menunjukkan cara mengetahui penyebab ANR pengiriman waktu tunggu input.
Vital Play dapat mendeteksi dan membantu men-debug beberapa penyebab ANR umum ini. Misalnya, jika data vital mendeteksi bahwa ANR terjadi karena pertentangan kunci, hal ini dapat meringkas masalah dan perbaikan yang direkomendasikan di bagian Insight ANR.
Tidak ada jendela yang difokuskan
Meskipun peristiwa seperti sentuhan dikirim langsung ke jendela yang relevan berdasarkan hit test, peristiwa seperti kunci memerlukan target. Target ini disebut sebagai jendela yang difokuskan. Hanya ada satu jendela yang difokuskan per tampilan, dan biasanya jendela yang saat ini berinteraksi dengan pengguna. Jika jendela yang difokuskan tidak dapat ditemukan, input akan memunculkan ANR tanpa jendela yang difokuskan. ANR tanpa jendela yang difokuskan adalah jenis ANR pengiriman input.
Periode waktu tunggu default: 5 detik.
Penyebab umum
ANR tanpa jendela yang difokuskan biasanya disebabkan oleh salah satu masalah berikut:
- Aplikasi melakukan terlalu banyak pekerjaan dan terlalu lambat untuk menggambar frame pertama.
- Jendela utama tidak dapat difokuskan. Jika jendela ditandai dengan
FLAG_NOT_FOCUSABLE
, pengguna tidak dapat mengirim peristiwa tombol ke jendela tersebut.
Kotlin
override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) window.addFlags(WindowManager.LayoutParams.FLAG_FLAG_NOT_FOCUSABLE) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); }
Waktu tunggu penerima siaran habis
ANR penerima siaran terjadi saat penerima siaran tidak menangani
siaran secara tepat waktu. Untuk penerima sinkron, atau penerima yang tidak memanggil
goAsync()
, waktu tunggu habis berarti onReceive()
tidak selesai tepat
waktu. Untuk penerima asinkron, atau penerima yang memanggil goAsync()
, waktu tunggu habis berarti
PendingResult.finish()
tidak dipanggil tepat waktu.
ANR penerima siaran sering terjadi di thread berikut:
- Thread utama, jika masalahnya adalah startup aplikasi lambat.
- Thread menjalankan penerima siaran, jika masalahnya adalah kode
onReceive()
lambat. - Thread pekerja siaran, jika masalahnya adalah kode siaran
goAsync()
lambat.
Untuk menghindari ANR penerima siaran, ikuti praktik terbaik berikut:
- Pastikan startup aplikasi berlangsung cepat, karena ini dihitung dalam waktu tunggu ANR jika aplikasi mulai menangani siaran.
- Jika
goAsync()
digunakan, pastikanPendingResult.finish()
dipanggil dengan cepat. Hal ini tunduk pada waktu tunggu ANR yang sama dengan penerima siaran sinkron. - Jika
goAsync()
digunakan, pastikan thread pekerja tidak digunakan bersama dengan operasi pemblokiran atau yang berjalan lama lainnya. - Sebaiknya gunakan
registerReceiver()
untuk menjalankan penerima siaran di thread non-utama, guna menghindari kode UI pemblokir berjalan di thread utama.
Periode waktu tunggu
Periode waktu tunggu menerima siaran bergantung pada apakah tanda intent latar depan telah ditetapkan atau tidak, serta versi platform.
Jenis intent | Android 13 dan yang lebih lama | Android 14 dan yang lebih baru |
---|---|---|
Intent prioritas latar depan ( |
10 detik |
10-20 detik, tergantung pada apakah proses kehabisan CPU |
Intent prioritas latar belakang ( |
60 detik |
60-120 detik, tergantung pada apakah proses kehabisan CPU |
Untuk mengetahui apakah tanda FLAG_RECEIVER_FOREGROUND
telah ditetapkan, cari "flg=" dalam
subjek ANR dan periksa keberadaan 0x10000000
. Jika bit ini ditetapkan, intent
telah menetapkan FLAG_RECEIVER_FOREGROUND
sehingga waktu tunggu lebih singkat.
Contoh subjek ANR dengan waktu tunggu siaran singkat (10-20 detik):
Broadcast of Intent { act=android.inent.action.SCREEN_ON flg=0x50200010 }
Contoh subjek ANR dengan waktu tunggu siaran lama (60-120 detik):
Broadcast of Intent { act=android.intent.action.TIME_SET flg=0x25200010 }
Cara waktu siaran diukur
Pengukuran durasi siaran dimulai saat siaran dikirim dari
system_server
ke aplikasi, dan selesai saat aplikasi selesai memproses
siaran. Jika proses aplikasi belum berjalan, proses aplikasi juga perlu melakukan cold start
dalam periode waktu tunggu ANR. Oleh karena itu, startup aplikasi yang lambat dapat mengakibatkan
ANR penerima siaran.
Gambar berikut mengilustrasikan linimasa ANR penerima siaran yang selaras dengan proses aplikasi tertentu.
Pengukuran waktu tunggu ANR berakhir saat penerima selesai memproses siaran: waktu terjadinya hal ini bergantung pada apakah siaran tersebut adalah penerima sinkron atau asinkron.
- Untuk penerima sinkron, pengukuran berhenti saat
onReceive()
ditampilkan. - Untuk penerima asinkron, pengukuran berhenti saat
PendingResult.finish()
dipanggil.
Penyebab umum
Berikut beberapa penyebab umum dan perbaikan yang disarankan untuk ANR penerima siaran.
Penyebab | Berlaku untuk | Yang terjadi | Perbaikan yang disarankan |
---|---|---|---|
Startup aplikasi lambat | Semua penerima | Aplikasi membutuhkan waktu terlalu lama untuk melakukan cold start. | Optimalkan pembukaan aplikasi yang lambat. |
onReceive() Tidak dijadwalkan | Semua penerima | Thread penerima siaran sedang sibuk melakukan pekerjaan lain dan tidak dapat
memulai metode onReceive() . | Jangan menjalankan tugas yang berjalan lama di thread penerima (atau memindahkan penerima ke thread khusus). |
onReceive() lambat | Semua penerima, tetapi terutama penerima sinkron | Metode onReceive() dimulai, tetapi
diblokir atau lambat sehingga tidak selesai tepat waktu. | Optimalkan kode penerima yang lambat. |
Tugas penerima asinkron tidak dijadwalkan | goAsync()
penerima | Metode onReceive() mencoba menjalankan pekerjaan
di kumpulan thread pekerja yang diblokir, sehingga pekerjaan tidak pernah dimulai. |
Optimalkan panggilan yang lambat atau pemblokir, atau gunakan thread berbeda untuk pekerja siaran vs tugas yang berjalan lama lainnya. |
Pekerja lambat atau diblokir | goAsync() penerima |
Ada operasi pemblokir atau lambat di suatu tempat dalam kumpulan thread pekerja
saat memproses siaran. Jadi, PendingResult.finish
tidak dipanggil tepat waktu. | Optimalkan kode penerima async
yang lambat. |
Lupa memanggil PendingResult.finish |
goAsync() penerima |
Panggilan ke finish() tidak ada di jalur kode. |
Pastikan finish() selalu dipanggil. |
Cara men-debug
Berdasarkan tanda tangan cluster dan laporan ANR, Anda dapat menemukan thread tempat penerima dijalankan, lalu kode tertentu yang tidak ada atau berjalan lambat.
Diagram alur berikut menunjukkan cara mengetahui penyebab ANR penerima siaran.
Menemukan kode penerima
Konsol Google Play menampilkan class penerima dan intent siaran dalam tanda tangan ANR. Cari hal berikut:
cmp=<receiver class>
act=<broadcast_intent>
Berikut adalah contoh tanda tangan ANR penerima siaran:
com.example.app.MyClass.myMethod
Broadcast of Intent { act=android.accounts.LOGIN_ACCOUNTS_CHANGED
cmp=com.example.app/com.example.app.MyAccountReceiver }
Menemukan thread yang menjalankan metode onReceive()
Jika Anda menggunakan Context.registerReceiver
untuk menentukan pengendali kustom,
itu adalah thread yang menjalankan pengendali ini. Jika tidak, thread tersebut adalah thread utama.
Contoh: tugas penerima asinkron tidak dijadwalkan
Bagian ini membahas contoh cara men-debug ANR penerima siaran.
Katakanlah tanda tangan ANR terlihat seperti berikut:
com.example.app.MyClass.myMethod
Broadcast of Intent {
act=android.accounts.LOG_ACCOUNTS_CHANGED cmp=com.example.app/com.example.app.MyReceiver }
Berdasarkan tanda tangan, sepertinya intent siaran adalah
android.accounts.LOG_ACCOUNTS_CHANGED
dan class penerima adalah
com.example.app.MyReceiver
.
Dari kode penerima, Anda dapat mengetahui bahwa kumpulan thread "BG Thread
[0,1,2,3]" melakukan pekerjaan utama untuk memproses siaran ini. Dengan melihat stack
dump, Anda dapat melihat bahwa keempat thread latar belakang (BG) memiliki pola yang sama:
keduanya menjalankan panggilan pemblokir, getDataSync
. Karena semua thread BG sibuk,
siaran tidak dapat diproses tepat waktu sehingga menyebabkan ANR.
BG Thread #0 (tid=26) Waiting
at jdk.internal.misc.Unsafe.park(Native method:0)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture:563)
at com.google.common.util.concurrent.ForwardingFuture.get(ForwardingFuture:68)
at com.example.app.getDataSync(<MyClass>:152)
...
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at com.google.android.libraries.concurrent.AndroidExecutorsModule.lambda$withStrictMode$5(AndroidExecutorsModule:451)
at com.google.android.libraries.concurrent.AndroidExecutorsModule$$ExternalSyntheticLambda8.run(AndroidExecutorsModule:1)
at java.lang.Thread.run(Thread.java:1012)
at com.google.android.libraries.concurrent.ManagedPriorityThread.run(ManagedPriorityThread:34)
There are several approaches to fix the issue:
- Find out why
getDataSync
is slow and optimize. - Don't run
getDataSync
on all four BG threads. - More generally, ensure that the BG thread pool isn't saturated with long-running operations.
- Use a dedicated thread pool for
goAsync
worker tasks. - Use an unbounded thread pool instead of the bounded BG thread pool
Example: slow app startup
A slow app startup can cause several types of ANRs, especially broadcast
receiver and execute service ANRs. The cause of an
ANR is likely slow app startup if you see ActivityThread.handleBindApplication
in the main thread stacks.
Execute service timeout
An execute service ANR happens when the app's main thread doesn't start a
service in time. Specifically, a service doesn't finish executing
onCreate()
and onStartCommand()
or onBind()
within the
timeout period.
Default timeout period: 20 seconds for foreground service; 200 seconds for
background service. The ANR timeout period includes the app cold start, if
necessary, and calls to onCreate(), onBind()
, or onStartCommand()
.
To avoid execute service ANRs, follow these general best practices:
- Make sure that app startup is fast, since it's counted in the ANR timeout if the app is started to run the service component.
- Make sure that the service's
onCreate()
,onStartCommand()
, andonBind()
methods are fast. - Avoid running any slow or blocking operations on the main thread from other components; these operations can prevent a service from starting quickly.
Common causes
The following table lists common causes of execute service ANRs and suggested fixes.
Cause | What | Suggested fix |
---|---|---|
Slow app startup | The app takes too long to perform a cold start. | Optimize slow app start. |
Slow onCreate(), onStartCommand (), or
onBind() |
The service component's onCreate(),
onStartCommand (), or onBind() method takes too long to
execute on the main thread. |
Optimize slow code. Move slow operations off the critical path where possible. |
Not scheduled (main thread blocked before onStart() ) |
The app's main thread is blocked by another component before the service can be started. | Move other component's work off the main thread. Optimize other component's blocking code. |
How to debug
From the cluster signature and ANR report in Google Play Console or Firebase Crashlytics, you can often determine the cause of the ANR based on what the main thread is doing.
The following flow chart describes how to debug an execute service ANR.
If you've determined that the execute service ANR is actionable, follow these steps to help resolve the issue:
Find the service component class in the ANR signature. In Google Play Console, the service component class is shown in the ANR signature. In the following example ANR details, it's
com.example.app/MyService
.com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly Executing service com.example.app/com.example.app.MyService
Determine whether the slow or block operation is part of app startup, the service component, or elsewhere by checking for the following important function call(s) in the main threads.
Function call(s) in main thread stacks What it means android.app.ActivityThread.handleBindApplication
App was starting up, so the ANR was caused by slow app start. <ServiceClass>.onCreate()
[...]
android.app.ActivityThread.handleCreateService
Service was being created, so the ANR was likely caused by slow onCreate()
code.<ServiceClass>.onBind()
[...]
android.app.ActivityThread.handleBindService
Service was being bound, so the ANR was likely caused by slow onBind()
code.<ServiceClass>.onStartCommand()
[...]
android.app.ActivityThread.handleServiceArgs
Service was being started, so the ANR was likely caused by slow onStartCommand()
code.For example, if the
onStartCommand()
method in theMyService
class is slow, the main threads will look like this:at com.example.app.MyService.onStartCommand(FooService.java:25) at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4820) at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(unavailable:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2289) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8176) at java.lang.reflect.Method.invoke(Native method:0)
Jika Anda tidak dapat melihat panggilan fungsi yang penting, ada beberapa kemungkinan lainnya:
- Layanan sedang berjalan atau dinonaktifkan, yang berarti stack diambil terlalu lambat. Dalam hal ini, Anda dapat mengabaikan ANR sebagai positif palsu.
- Komponen aplikasi lain sedang berjalan, misalnya, penerima siaran. Dalam hal ini, thread utama kemungkinan diblokir di komponen ini sehingga mencegah layanan dimulai.
Jika Anda melihat panggilan fungsi kunci dan dapat mengetahui di mana ANR terjadi secara umum, periksa stack thread utama lainnya untuk menemukan operasi yang lambat dan mengoptimalkannya atau memindahkannya dari jalur penting.
- Pastikan startup aplikasi cepat, karena dihitung dalam waktu tunggu ANR jika aplikasi mulai menjalankan penyedia konten.
- Pastikan kueri penyedia konten cepat.
- Jangan melakukan banyak panggilan binder pemblokir serentak yang dapat memblokir semua thread binder aplikasi.
- Pembuangan stack terlambat. Thread pulih selama periode singkat antara terpicunya ANR dan pembuangan stack. Latensi di Pixel pada Android 13 adalah sekitar 100 md, tetapi dapat melebihi 1 dtk. Latensi di Pixel pada Android 14 biasanya di bawah 10 md.
- Kesalahan atribusi thread. Thread yang digunakan untuk membuat tanda tangan ANR bukanlah thread tidak responsif sebenarnya yang menyebabkan ANR. Dalam hal ini, cobalah mengetahui apakah jenis ANR adalah salah satu dari berikut:
- Masalah di seluruh sistem. Proses ini tidak dijadwalkan karena beban sistem yang berat atau masalah di server sistem.
- Pengambilan stack menghabiskan waktu terlalu lama dan waktu habis.
- Proses ini berhenti atau dihentikan sebelum stack diambil.
Untuk mengetahui informasi selengkapnya tentang layanan, lihat halaman berikut:
Penyedia konten tidak merespons
ANR penyedia konten terjadi saat penyedia konten jarak jauh menghabiskan waktu lebih lama dari periode waktu tunggu untuk merespons kueri, dan dihentikan.
Periode waktu tunggu default: ditentukan oleh penyedia konten menggunakan
ContentProviderClient.setDetectNotResponding
. Periode waktu tunggu ANR
mencakup total waktu yang dibutuhkan untuk menjalankan kueri penyedia konten jarak jauh, yang
termasuk melakukan cold start aplikasi jarak jauh jika belum berjalan.
Untuk menghindari ANR penyedia konten, ikuti praktik terbaik berikut:
Penyebab umum
Tabel berikut mencantumkan penyebab umum ANR penyedia konten dan perbaikan yang disarankan.
Penyebab | Yang terjadi | Sinyal | Perbaikan yang disarankan |
---|---|---|---|
Kueri penyedia konten lambat | Penyedia konten menghabiskan waktu terlalu lama untuk dijalankan atau sedang diblokir. | Frame android.content.ContentProvider$Transport.query
berada di thread binder. |
Optimalkan kueri penyedia konten. Cari tahu apa yang memblokir thread binder. |
Startup aplikasi lambat | Aplikasi penyedia konten menghabiskan waktu terlalu lama untuk startup. | Frame ActivityThread.handleBindApplication berada di
thread utama. |
Optimalkan startup aplikasi. |
Kehabisan thread binder—semua thread binder sibuk | Semua thread binder sibuk melayani permintaan sinkron lainnya sehingga panggilan binder penyedia konten tidak dapat berjalan. | Aplikasi tidak dimulai, semua thread binder sibuk, dan penyedia konten tidak berjalan. | Kurangi beban pada thread binder. Artinya, kurangi panggilan binder keluar yang sinkron atau lakukan lebih sedikit pekerjaan saat menangani panggilan masuk. |
Cara men-debug
Untuk men-debug ANR penyedia konten menggunakan tanda tangan cluster dan laporan ANR di Konsol Google Play atau Firebase Crashlytics, lihat apa yang dilakukan thread utama dan thread binder.
Diagram alur berikut menjelaskan cara men-debug ANR penyedia konten:
Cuplikan kode berikut menunjukkan tampilan thread binder saat diblokir karena kueri penyedia konten yang lambat. Dalam hal ini, kueri penyedia konten menunggu kunci saat membuka database.
binder:11300_2 (tid=13) Blocked
Waiting for osm (0x01ab5df9) held by at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers:182)
at com.example.app.MyClass.blockingGetOpenDatabase(FooClass:171)
[...]
at com.example.app.MyContentProvider.query(MyContentProvider.java:915)
at android.content.ContentProvider$Transport.query(ContentProvider.java:292)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:107)
at android.os.Binder.execTransactInternal(Binder.java:1339)
at android.os.Binder.execTransact(Binder.java:1275)
Cuplikan kode berikut menunjukkan tampilan thread utama saat diblokir karena startup aplikasi yang lambat. Dalam hal ini, startup aplikasi lambat karena pertentangan kunci selama inisialisasi dagger.
main (tid=1) Blocked
[...]
at dagger.internal.DoubleCheck.get(DoubleCheck:51)
- locked 0x0e33cd2c (a qsn)at dagger.internal.SetFactory.get(SetFactory:126)
at com.myapp.Bar_Factory.get(Bar_Factory:38)
[...]
at com.example.app.MyApplication.onCreate(DocsApplication:203)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1316)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6991)
at android.app.ActivityThread.-$$Nest$mhandleBindApplication(unavailable:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2235)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8170)
at java.lang.reflect.Method.invoke(Native method:0)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Respons tugas lambat
ANR respons tugas lambat terjadi saat aplikasi menghabiskan waktu terlalu lama untuk merespons
JobService.onStartJob()
atau JobService.onStopJob()
, atau menghabiskan waktu terlalu lama untuk
memberikan notifikasi menggunakan JobService.setNotification()
. Hal ini menunjukkan bahwa
thread utama aplikasi diblokir untuk melakukan hal lain.
Jika ada masalah dengan JobService.onStartJob()
atau JobService.onStopJob()
,
periksa apa yang terjadi di thread utama. Jika ada masalah dengan
JobService.setNotification()
, pastikan untuk menghubunginya secepat mungkin.
Tidak perlu melakukan banyak hal sebelum memberikan notifikasi.
ANR Misteri
Terkadang tidak jelas mengapa ANR terjadi, atau tidak ada informasi yang memadai untuk men-debug-nya di tanda tangan cluster dan laporan ANR. Dalam kasus ini, masih ada beberapa langkah yang dapat Anda ambil untuk mengetahui apakah ANR dapat ditindaklanjuti.
Antrean pesan tidak ada aktivitas atau nativePollOnce
Jika Anda melihat frame android.os.MessageQueue.nativePollOnce
dalam
stack, hal ini sering kali menunjukkan bahwa thread yang dicurigai tidak responsif sebenarnya
tidak ada aktivitas dan menunggu pesan looper. Di Konsol Google Play, detail ANR
akan terlihat seperti ini:
Native method - android.os.MessageQueue.nativePollOnce
Executing service com.example.app/com.example.app.MyService
Misalnya, jika thread utama tidak ada aktivitas, stack-nya akan terlihat seperti ini:
"main" tid=1 NativeMain threadIdle
#00 pc 0x00000000000d8b38 /apex/com.android.runtime/lib64/bionic/libc.so (__epoll_pwait+8)
#01 pc 0x0000000000019d88 /system/lib64/libutils.so (android::Looper::pollInner(int)+184)
#02 pc 0x0000000000019c68 /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+112)
#03 pc 0x000000000011409c /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+44)
at android.os.MessageQueue.nativePollOnce (Native method)
at android.os.MessageQueue.next (MessageQueue.java:339) at android.os.Looper.loop (Looper.java:208)
at android.app.ActivityThread.main (ActivityThread.java:8192)
at java.lang.reflect.Method.invoke (Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:626)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1015)
Ada beberapa alasan mengapa thread yang dicurigai tidak responsif bisa menjadi tidak ada aktivitas:
Tidak ada frame stack
Beberapa laporan ANR tidak menyertakan stack dengan ANR, yang berarti pembuangan stack gagal saat membuat laporan ANR. Ada beberapa kemungkinan alasan frame stack hilang:
[...]
--- CriticalEventLog ---
capacity: 20
timestamp_ms: 1666030897753
window_ms: 300000
libdebuggerd_client: failed to read status response from tombstoned: timeout reached?
----- Waiting Channels: pid 7068 at 2022-10-18 02:21:37.<US_SOCIAL_SECURITY_NUMBER>+0800 -----
[...]
ANR tanpa frame stack tidak dapat ditindaklanjuti dari tanda tangan cluster atau laporan ANR. Untuk men-debug, lihat cluster lain untuk aplikasi tersebut, karena jika masalahnya cukup besar, cluster tersebut biasanya akan memiliki cluster sendiri yang disertai frame stack. Opsi lainnya adalah melihat rekaman aktivitas Perfetto.
Masalah umum
Menyimpan timer dalam proses aplikasi untuk tujuan menyelesaikan penanganan siaran sebelum ANR terpicu mungkin tidak akan bekerja dengan benar karena sistem memantau ANR dengan cara asinkron.