Praktik terbaik manajemen memori

Dokumen ini menganggap Anda telah mengikuti panduan praktik terbaik untuk aplikasi Android berdasarkan manajemen memori, seperti Mengelola memori aplikasi.

Pengantar

Kebocoran memori adalah jenis kebocoran resource yang terjadi saat program komputer tidak melepaskan memori yang dialokasikan yang tidak lagi dibutuhkan. Kebocoran dapat menyebabkan aplikasi meminta memori dari OS melebihi yang tersedia, sehingga membuat aplikasi error. Sejumlah praktik yang tidak tepat dapat menyebabkan kebocoran memori di aplikasi Android, seperti tidak membuang resource secara benar atau tidak membatalkan pendaftaran pemroses saat tidak lagi dibutuhkan.

Dokumen ini menguraikan beberapa praktik terbaik kepada Anda untuk membantu mencegah, mendeteksi, dan menyelesaikan masalah kebocoran memori di kode Anda. Jika Anda sudah mencoba semua metode dalam dokumen ini dan menduga ada kebocoran memori di SDK kami, lihat Cara melaporkan masalah terkait SDK Google.

Sebelum menghubungi dukungan

Sebelum Anda melaporkan kebocoran memori kepada tim dukungan Google, ikuti praktik terbaik beserta langkah-langkah proses debug yang diberikan dalam dokumen ini untuk memastikan tidak ada error di kode Anda. Jika tidak berhasil menyelesaikan masalah Anda, langkah-langkah ini dapat memberikan informasi yang dibutuhkan tim dukungan Google untuk membantu Anda.

Mencegah kebocoran memori

Ikuti praktik terbaik ini untuk membantu menghindari beberapa penyebab paling umum kebocoran memori di kode yang menggunakan SDK Google.

Praktik terbaik untuk aplikasi Android

Pastikan Anda telah melakukan semua tindakan berikut di aplikasi Android:

  1. Melepaskan resource yang tidak digunakan.
  2. Membatalkan pendaftaran pemroses saat tidak lagi dibutuhkan.
  3. Membatalkan tugas saat tidak dibutuhkan.
  4. Meneruskan metode siklus proses untuk melepaskan resource.
  5. Menggunakan SDK versi terbaru

Untuk mengetahui detail spesifik terkait setiap praktik terbaik ini, lihat bagian berikut.

Melepaskan resource yang tidak digunakan

Saat aplikasi Android Anda menggunakan resource, pastikan untuk melepaskan resource tersebut saat tidak lagi dibutuhkan. Jika tidak dilakukan, resource akan terus mengambil memori bahkan setelah aplikasi Anda tidak lagi menggunakannya. Untuk informasi selengkapnya, tinjau Siklus proses aktivitas di dokumentasi Android.

Melepaskan referensi GoogleMap yang tidak berlaku di GeoSDK

Kesalahan umum yang sering terjadi adalah GoogleMap dapat menyebabkan kebocoran memori jika di-cache menggunakan NavigationView atau MapView. GoogleMap memiliki hubungan 1:1 dengan NavigationView atau MapView tempat GoogleMap diambil. Anda harus memastikan bahwa GoogleMap tidak di-cache, atau referensi dilepaskan saat NavigationView#onDestroy atau MapView#onDestroy dipanggil. Jika menggunakan NavigationSupportFragment, MapSupportFragment, atau fragmen Anda sendiri yang menggabungkan tampilan ini, referensi harus dilepaskan di Fragment#onDestroyView.

class NavFragment : SupportNavigationFragment() {

  var googleMap: GoogleMap?

  override fun onCreateView(
    inflater: LayoutInflater,
    parent: ViewGroup?,
    savedInstanceState: Bundle?,
  ): View  {
    super.onCreateView(inflater,parent,savedInstanceState)
    getMapAsync{map -> googleMap = map}
  }

  override fun onDestroyView() {
    googleMap = null
  }
}

Membatalkan pendaftaran pemroses saat tidak lagi dibutuhkan

Saat aplikasi Android Anda mendaftarkan pemroses untuk sebuah peristiwa, seperti klik tombol atau perubahan status tampilan, pastikan untuk membatalkan pendaftaran pemroses saat aplikasi tidak perlu lagi memantau peristiwa tersebut. Jika tidak dilakukan, pemroses akan terus mengambil memori bahkan setelah aplikasi Anda tidak lagi menggunakannya.

Misalnya, aplikasi Anda menggunakan Navigation SDK dan memanggil pemroses berikut untuk memproses peristiwa kedatangan: metode addArrivalListener untuk memproses peristiwa kedatangan, aplikasi juga akan memanggil removeArrivalListener saat tidak perlu lagi memantau peristiwa kedatangan.

var arrivalListener: Navigator.ArrivalListener? = null

fun registerNavigationListeners() {
  arrivalListener =
    Navigator.ArrivalListener {
      ...
    }
  navigator.addArrivalListener(arrivalListener)
}

override fun onDestroy() {
  navView.onDestroy()
  if (arrivalListener != null) {
    navigator.removeArrivalListener(arrivalListener)
  }

  ...
  super.onDestroy()
}

Membatalkan tugas saat tidak dibutuhkan

Saat aplikasi Android memulai tugas asinkron, seperti download atau permintaan jaringan, pastikan Anda membatalkan tugas tersebut jika sudah selesai. Jika tidak dibatalkan, tugas akan terus berjalan di latar belakang bahkan setelah aplikasi selesai dengan tugas tersebut.

Untuk detail selengkapnya tentang praktik terbaik, lihat Mengelola memori aplikasi di dokumentasi Android.

Meneruskan metode siklus proses untuk melepaskan resource

Jika aplikasi Anda menggunakan Navigation SDK atau Maps SDK, pastikan untuk melepaskan resource dengan meneruskan metode siklus proses (ditampilkan dalam cetak tebal) ke navView. Anda dapat melakukannya menggunakan NavigationView di Navigation SDK atau MapView di Maps SDK atau Navigation SDK. Anda dapat juga menggunakan SupportNavigationFragment atau SupportMapFragment daripada langsung menggunakan NavigationView dan MapView. Fragmen dukungan ini menangani penerusan metode siklus proses.

class NavViewActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...
    navView = ...
    navView.onCreate(savedInstanceState)
    ...
  }

  override fun onSaveInstanceState(savedInstanceState: Bundle) {
    super.onSaveInstanceState(savedInstanceState)
    navView.onSaveInstanceState(savedInstanceState)
  }

  override fun onTrimMemory(level: Int) {
    super.onTrimMemory(level)
    navView.onTrimMemory(level)
  }

  /* Same with
    override fun onStart()
    override fun onResume()
    override fun onPause()
    override fun onConfigurationChanged(...)
    override fun onStop()
    override fun onDestroy()
  */
}

Menggunakan SDK versi terbaru

SDK Google terus diupdate dengan fitur baru, perbaikan bug, dan peningkatan performa. Pastikan aplikasi Anda menggunakan SDK versi terbaru agar dapat menerima perbaikan ini.

Men-debug kebocoran memori

Jika masih terjadi kebocoran memori setelah menerapkan semua saran relevan yang diuraikan sebelumnya dalam dokumen ini, ikuti proses ini untuk melakukan debug.

Sebelum memulai, Anda harus memahami cara Android mengelola memori. Untuk mendapatkan informasi, baca Ringkasan manajemen memori untuk Android.

Untuk men-debug kebocoran memori, ikuti proses berikut:

  1. Membuat ulang masalah. Langkah ini penting untuk melakukan proses debug pada masalah tersebut.
  2. Memeriksa apakah penggunaan memori sesuai perkiraan. Pastikan bahwa peningkatan penggunaan yang terlihat seperti kebocoran sebenarnya bukan memori yang diperlukan untuk menjalankan aplikasi Anda.
  3. Men-debug pada tingkat yang tinggi. Ada beberapa utilitas yang dapat Anda gunakan untuk men-debug. Tiga set alat standar yang berbeda dapat membantu men-debug masalah memori di Android: Android Studio, Perfetto, dan utilitas command line Android Debug Bridge (adb).
  4. Memeriksa penggunaan memori aplikasi. Dapatkan heap dump dan pelacakan alokasi, lalu lakukan analisis.
  5. Memperbaiki kebocoran memori.

Bagian berikut akan membahas langkah-langkah ini secara detail.

Langkah 1: Buat ulang masalah

Jika Anda belum dapat membuat ulang masalah tersebut, pertimbangkan dulu skenario yang dapat menyebabkan kebocoran memori. Langsung melihat heap dump mungkin membantu jika Anda tahu masalah tersebut sudah dibuat ulang. Namun, jika Anda baru saja mendapatkan heap dump saat aplikasi dimulai atau pada waktu acak lainnya, Anda mungkin belum mengaktifkan kondisi untuk memicu kebocoran. Pertimbangkan untuk menggunakan berbagai skenario saat mencoba membuat ulang masalah:

  • Serangkaian fitur apa saja yang diaktifkan?

  • Urutan tindakan pengguna khusus manakah yang memicu kebocoran?

    • Apakah Anda sudah mencoba beberapa iterasi untuk mengaktifkan urutan ini?
  • Pada kondisi siklus proses manakah aplikasi disikluskan?

    • Apakah Anda sudah mencoba beberapa iterasi melalui kondisi siklus proses yang berbeda?

Pastikan Anda dapat membuat ulang masalah di SDK versi terbaru. Masalah dari versi sebelumnya mungkin telah diperbaiki.

Langkah 2: Periksa apakah penggunaan memori untuk aplikasi sesuai perkiraan

Setiap fitur memerlukan memori tambahan. Saat Anda men-debug skenario yang berbeda, pertimbangkan apakah skenario ini bisa dianggap sebagai penggunaan yang diperkirakan atau tidak atau benar-benar kebocoran memori. Misalnya, untuk berbagai fitur atau tugas pengguna, pertimbangkan kemungkinan berikut:

  • Kemungkinan besar terjadi kebocoran: Mengaktifkan skenario melalui beberapa iterasi akan mengakibatkan peningkatan penggunaan memori dari waktu ke waktu.

  • Kemungkinan besar terjadi penggunaan memori yang diperkirakan: Memori diklaim kembali setelah skenario dihentikan.

  • Kemungkinan terjadi penggunaan memori yang diperkirakan: Penggunaan memori meningkat selama jangka waktu tertentu kemudian menurun. Hal ini dapat disebabkan oleh cache yang dibatasi atau penggunaan memori lainnya yang diperkirakan.

Jika perilaku aplikasi menunjukkan kemungkinan besar terjadi penggunaan memori yang diperkirakan, masalah tersebut bisa diatasi dengan mengelola memori aplikasi Anda. Untuk mendapatkan bantuan, lihat Mengelola memori aplikasi.

Langkah 3: Lakukan debug di tingkat tinggi

Saat Anda men-debug kebocoran memori, mulailah di tingkat tinggi, lalu lihat perincian setelah Anda mempersempit kemungkinannya. Gunakan salah satu dari alat proses debug tingkat tinggi berikut untuk menganalisis terlebih dahulu apakah ada kebocoran dari waktu ke waktu:

Memory Profiler Android Studio

Alat ini memberi Anda histogram visual tentang memori yang digunakan. Heap dump dan pelacakan alokasi juga dapat dipicu dari antarmuka yang sama ini. Alat ini adalah rekomendasi default. Untuk informasi selengkapnya, lihat Memory Profiler Android Studio.

Penghitung Memori Perfetto

Perfetto memberi Anda kontrol yang akurat terhadap pelacakan beberapa metrik dan menyajikan semuanya dalam satu histogram. Untuk informasi selengkapnya, lihat Penghitung Memori Perfetto.

Antarmuka pengguna Perfetto

Utilitas command line Android debug bridge (adb)

Sebagian besar data yang dapat dilacak dengan Perfetto juga tersedia sebagai utilitas command line adb yang kuerinya dapat Anda kirim secara langsung. Dua contoh pentingnya adalah:

  • Meminfo memungkinkan Anda melihat informasi memori mendetail di waktu tertentu.

  • Procstats memberikan sejumlah statistik agregat yang penting dari waktu ke waktu.

Statistik penting yang harus dilihat di sini adalah jejak memori fisik maksimum (maxRSS) yang dibutuhkan aplikasi dari waktu ke waktu. MaxPSS mungkin tidak terlalu akurat. Cara untuk meningkatkan akurasi, lihat flag adb shell dumpsys procstats --help –start-testing.

Pelacakan alokasi

Pelacakan alokasi mengidentifikasi stack trace tempat memori dialokasikan dan apakah memori belum dilepaskan. Langkah ini terutama berguna saat melacak kebocoran di kode native. Karena fungsinya untuk mengidentifikasi stack trace, alat ini sangat efektif untuk men-debug akar masalah dengan cepat atau mencari tahu cara membuat ulang masalah. Untuk langkah-langkah tentang cara menggunakan pelacakan alokasi, lihat Men-debug memori di kode native dengan pelacakan alokasi.

Langkah 4: Periksa penggunaan memori aplikasi dengan heap dump

Salah satu cara untuk mendeteksi kebocoran memori adalah mendapatkan heap dump aplikasi Anda dan kemudian memeriksanya apakah ada kebocoran. Heap dump adalah snapshot dari semua objek di memori aplikasi. Heap dump dapat digunakan untuk mendiagnosis kebocoran memori dan masalah lain yang terkait memori.

Android Studio dapat mendeteksi kebocoran memori yang tidak dapat diatasi oleh GC. Saat Anda merekam heap dump, Android Studio memeriksa apakah ada aktivitas atau fragmen yang masih dapat dijangkau tetapi sudah dihancurkan.

  1. Merekam heap dump.
  2. Menganalisis heap dump untuk menemukan kebocoran memori.
  3. Memperbaiki kebocoran memori.

Untuk mengetahui detailnya, lihat bagian berikut.

Merekam heap dump

Untuk merekam heap dump, Anda dapat menggunakan Android Debug Bridge (adb) atau Memory Profiler Android Studio.

Menggunakan adb untuk merekam heap dump

Untuk merekam heap dump menggunakan adb, ikuti langkah-langkah berikut:

  1. Hubungkan perangkat Android ke komputer.
  2. Buka command prompt dan arahkan ke direktori tempat alat adb berada.
  3. Untuk merekam heap dump, jalankan perintah ini:

    adb shell am dumpheap my.app.name $PHONE_FILE_OUT

  4. Untuk mengambil heap dump, jalankan perintah ini:

    adb pull $PHONE_FILE_OUT $LOCAL_FILE.

Menggunakan Android Studio untuk merekam heap dump

Untuk merekam heap dump menggunakan Memory Profiler Android Studio, ikuti langkah-langkah berikut di bagian Merekam heap dump Android.

Menganalisis heap dump untuk menemukan kebocoran memori

Setelah merekam heap dump, Anda dapat menggunakan Memory Profiler Android Studio untuk menganalisisnya. Untuk melakukannya, ikuti langkah-langkah ini:

  1. Buka project Android Anda di Android Studio.

  2. Pilih Run, lalu pilih konfigurasi Debug.

  3. Buka tab Android Profiler.

  4. Pilih Memory.

  5. Pilih Open heap dump dan pilih file heap dump yang Anda buat. Memory profiler menampilkan grafik penggunaan memori aplikasi Anda.

  6. Gunakan grafik untuk menganalisis heap dump:

    • Identifikasi objek yang tidak lagi digunakan.

    • Identifikasi objek yang menggunakan banyak memori.

    • Lihat berapa banyak memori yang digunakan setiap objek.

  7. Gunakan informasi ini untuk mempersempit atau menemukan sumber kebocoran memori dan memperbaikinya.

Langkah 5: Perbaiki kebocoran memori

Setelah mengidentifikasi sumber kebocoran memori, Anda dapat memperbaikinya. Memperbaiki kebocoran memori di aplikasi Android akan membantu meningkatkan performa dan stabilitas aplikasi Anda. Bergantung pada skenario, detailnya bisa sangat bervariasi. Namun, saran berikut dapat membantu:

Alat proses debug lainnya

Setelah langkah-langkah ini diselesaikan, jika Anda masih belum menemukan dan memperbaiki kebocoran memori, cobalah alat berikut:

Men-debug memori di kode native dengan pelacakan alokasi

Meskipun Anda tidak langsung menggunakan kode native, beberapa library Android umum menggunakannya, termasuk SDK Google. Jika Anda merasa kebocoran memori terjadi di kode native, ada beberapa alat yang dapat Anda gunakan untuk men-debugnya. Pelacakan alokasi dengan Android Studio atau heapprofd (juga kompatibel dengan Perfetto) adalah cara ideal untuk mengidentifikasi kemungkinan penyebab kebocoran memori dan sering kali menjadi cara tercepat untuk men-debug.

Pelacakan alokasi juga memiliki keunggulan unik yaitu mengizinkan Anda untuk membagikan hasil tanpa menyertakan informasi sensitif yang dapat ditemukan di heap.

Mengidentifikasi kebocoran dengan LeakCanary

LeakCanary adalah alat canggih untuk mengidentifikasi kebocoran memori di aplikasi Android. Untuk mempelajari lebih lanjut cara menggunakan LeakCanary di aplikasi Anda, kunjungi LeakCanary.

Cara melaporkan masalah terkait SDK Google

Jika Anda telah mencoba semua metode dalam dokumen ini dan menduga ada kebocoran memori di SDK kami, hubungi dukungan pelanggan dengan memberikan sebanyak mungkin informasi berikut:

  • Langkah-langkah untuk membuat ulang kebocoran memori. Jika langkah-langkah tersebut memerlukan coding yang kompleks, menyalin kode yang mereplikasi masalah ke aplikasi contoh dan memberikan langkah tambahan yang perlu diambil di UI untuk memicu kebocoran mungkin akan membantu.

  • Heap dump yang direkam dari aplikasi Anda dengan masalah yang dibuat ulang. Rekam heap dump di dua titik yang berbeda saat terindikasi penggunaan memori meningkat secara signifikan.

  • Jika kebocoran memori native diperkirakan terjadi, bagikan output pelacakan alokasi dari heapprofd.

  • Laporan bug diambil setelah Anda membuat ulang kondisi kebocoran.

  • Stack trace untuk error terkait memori.

    Catatan penting: Stack trace itu sendiri biasanya tidak memadai untuk men-debug masalah memori, jadi pastikan Anda juga memberikan salah satu bentuk informasi lainnya.