Mendiagnosis dan memperbaiki ANR

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.

Gambar 1. Cara men-debug ANR pengiriman 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.

Gambar 2. Deteksi ANR vital Play.

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 goAync(), 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, pastikan PendingResult.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

(FLAG_RECEIVER_FOREGROUND ditetapkan)

10 detik

10-20 detik, tergantung pada apakah proses kehabisan CPU

Intent prioritas latar belakang

(FLAG_RECEIVER_FOREGROUND tidak ditetapkan)

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.

Gambar 3. Linimasa ANR penerima siaran.

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.
Gambar 4. Endpoint pengukuran waktu tunggu ANR untuk penerima sinkron dan asinkron.

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 yang 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.

Gambar 5. Cara men-debug 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(), and onBind() 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.

Figure 6. 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:

  1. 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
    
  2. 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 the MyService 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.
  3. 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.

  4. 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:

    • 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.

    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:

    Gambar 7. 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:

    • 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.

    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:

    • Pengambilan stack menghabiskan waktu terlalu lama dan waktu habis.
    • Proses ini berhenti atau dihentikan sebelum stack diambil.
    [...]
    
    --- 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.