Dokumen ini menunjukkan cara mengidentifikasi thread yang tidak responsif dalam stack dump ANR. Thread yang tidak responsif berbeda-beda menurut jenis ANR, seperti yang ditunjukkan dalam tabel berikut.
Jenis ANR | Thread yang tidak responsif |
---|---|
Pengiriman input | Thread utama |
Pengiriman input tanpa jendela yang difokuskan | Thread utama. Jenis ANR ini biasanya tidak disebabkan oleh thread yang diblokir. |
Penerima siaran (sinkron) | Thread menjalankan
onReceive() .
Ini adalah thread utama, kecuali jika pengendali kustom pada thread non-utama
ditentukan menggunakan
Context.registerReceiver . |
Penerima siaran (asinkron) | Periksa kode untuk melihat thread atau kumpulan thread yang bertanggung jawab
melakukan tugas untuk memproses siaran setelah
goAsync
dipanggil. |
Mengeksekusi waktu tunggu layanan | Thread utama |
Layanan latar depan dimulai | Thread utama |
Penyedia konten tidak merespons | Atau:
|
Tidak ada respons untuk
onStartJob
atau
onStopJob |
Thread utama |
Terkadang thread tidak responsif karena akar masalah dalam thread atau proses yang berbeda. Thread tidak dapat merespons karena menunggu hal berikut:
- Kunci yang dipegang oleh thread lain.
- Panggilan binder lambat ke proses yang berbeda.
Penyebab umum thread yang tidak responsif
Berikut adalah penyebab umum thread yang tidak responsif.
Panggilan binder lambat
Meskipun sebagian besar panggilan binder berlangsung dengan cepat, longtail-nya bisa sangat lambat. Hal ini lebih mungkin terjadi jika perangkat dimuat atau thread balasan binder lambat, seperti dari pertentangan kunci, banyak panggilan binder yang masuk, atau waktu tunggu hardware abstraction layer (HAL).
Anda dapat mengatasi hal ini dengan memindahkan panggilan binder sinkron ke thread latar belakang jika memungkinkan. Jika panggilan harus terjadi pada thread utama, cari tahu penyebab panggilan lambat. Cara terbaik untuk melakukannya adalah dari rekaman aktivitas Perfetto.
Cari BinderProxy.transactNative
atau Binderproxy.transact
di stack.
Hal ini berarti panggilan binder sedang berlangsung. Dengan mengikuti dua baris ini, Anda dapat melihat
API binder yang dipanggil. Pada contoh berikut, panggilannya adalah ke
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)
...
Banyak panggilan binder berturut-turut
Melakukan banyak panggilan binder berturut-turut dalam loop padat dapat memblokir thread dalam jangka waktu yang lama.
Pemblokiran I/O
Jangan pernah memblokir I/O di thread utama. Hal ini adalah antipola.
Pertentangan kunci
Jika thread diblokir saat mendapatkan kunci, hal ini dapat menyebabkan ANR.
Contoh berikut menunjukkan thread utama diblokir saat mencoba mendapatkan kunci:
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)
[...]
Thread yang diblokir membuat permintaan HTTP untuk mendownload video:
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)
[...]
Frame mahal
Merender terlalu banyak hal dalam satu frame dapat menyebabkan thread utama tidak responsif selama durasi frame, seperti berikut:
- Merender banyak item di luar layar yang tidak perlu.
- Menggunakan algoritma yang tidak efisien, seperti
O(n^2)
, saat merender banyak elemen UI.
Diblokir oleh komponen lain
Jika komponen lain, seperti penerima siaran, memblokir thread utama selama lebih dari lima detik, hal ini dapat menyebabkan ANR pada pengiriman input dan jank serius.
Hindari melakukan tugas berat pada thread utama dalam komponen aplikasi. Jalankan penerima siaran di thread lain jika memungkinkan.