LeakCanary — adalah pustaka sumber terbuka dari Square untuk deteksi otomatis kebocoran memori di aplikasi Android. Pustaka ini terintegrasi ke dalam proses pengembangan dan melacak siklus hidup Activity, Fragment, ViewModel, dan komponen lainnya secara real-time, menandai kebocoran segera setelah terjadi. Menurut data Square Open Source, pustaka ini digunakan di ribuan proyek dan dianggap sebagai standar de facto untuk diagnostik memori di Android.
Poin Utama
LeakCanary — adalah pustaka untuk deteksi otomatis kebocoran memori di aplikasi Android, yang dikembangkan oleh perusahaan Square. Pustaka ini tertanam dalam proses pembangunan aplikasi dan secara otomatis melacak ketika objek yang seharusnya dihancurkan (Activity, Fragment, View) tetap berada di memori. Saat kebocoran terdeteksi, LeakCanary membuat heap dump dan menganalisis rantai referensi yang menahan objek.
Pustaka ini telah menjadi standar di komunitas Android: menurut data GitHub, proyek ini telah mengumpulkan lebih dari 28 ribu bintang dan digunakan di aplikasi Google, Uber, Airbnb, dan Facebook. LeakCanary tersedia dalam dua versi utama: klasik 1.x (dengan konfigurasi manual) dan modern 2.x (integrasi otomatis melalui ContentProvider). Versi 2.x tidak memerlukan modifikasi kelas Application — satu dependensi sudah cukup untuk berfungsi penuh.
Tugas utama LeakCanary adalah mendeteksi situasi ketika sebuah objek terus ada di memori setelah siklus hidupnya selesai. Ini tipikal untuk kebocoran melalui field statis, singleton, callback yang tidak terdaftar, kelas anonim, dan penutupan yang menangkap objek eksternal.
Kebocoran memori di Android lebih kritis daripada di desktop karena terbatasnya jumlah RAM pada perangkat seluler. Bahkan kebocoran 5–10 MB pada setiap perpindahan layar dapat menyebabkan OutOfMemoryError setelah 30–40 menit penggunaan aplikasi. LeakCanary mendeteksi masalah seperti itu pada tahap pengembangan, tanpa menunggu kegagalan di produksi.
LeakCanary menggunakan referensi lemah (WeakReference) dalam kombinasi dengan panggilan paksa garbage collector. Ketika Activity atau Fragment memanggil onDestroy, LeakCanary membuat WeakReference untuk objek ini dan menjalankan GC setelah penundaan singkat (secara default 5 detik). Jika setelah GC objek masih dapat diakses melalui WeakReference, berarti objek tersebut ditahan oleh referensi kuat — kebocoran dicatat.
Setelah mendeteksi kebocoran, LeakCanary membuat heap dump (cuplikan lengkap memori aplikasi dalam format HPROF). Kemudian penganalisis bawaan (Shark untuk versi 2.x) membangun grafik keterjangkauan dari GC Roots ke objek yang bocor dan menemukan jalur terpendek — rantai referensi yang menahan objek di memori.
// Logika deteksi LeakCanary yang disederhanakan
class ObjectWatcher {
private val watchedReferences = CopyOnWriteArrayList<KeyedWeakReference>()
fun watch(watchedObject: Any, description: String) {
val reference = KeyedWeakReference(watchedObject, description)
watchedReferences.add(reference)
BackgroundHandler.postDelayed({
checkForLeaks()
}, 5000)
}
private fun checkForLeaks() {
GcTrigger.runGc() // GC paksa
for (ref in watchedReferences) {
if (ref.get() != null) {
onLeakFound(ref) // objek bertahan dari GC — ini kebocoran
}
}
}
}
Poin kuncinya — panggilan paksa GcTrigger.runGc(). Tanpanya, tidak mungkin membedakan objek yang benar-benar bocor dari objek yang GC belum sempat kumpulkan. LeakCanary melakukan ini hingga tiga kali: jika setelah tiga siklus GC objek masih ada di memori — kebocoran dikonfirmasi.
Shark — adalah penganalisis heap dump bawaan di LeakCanary 2.x, yang ditulis dalam Kotlin. Berbeda dengan penganalisis sebelumnya HAHA, Shark tidak memuat seluruh file HPROF ke dalam memori, tetapi menelusuri grafik objeknya dengan alokasi minimal. Ini mengurangi konsumsi RAM selama analisis dari 50 MB menjadi 2–5 MB dan mempersingkat waktu analisis dari 30 detik menjadi 1–3 detik.
Instalasi LeakCanary 2.x di proyek Android modern membutuhkan satu baris di build.gradle. Pustaka menggunakan ContentProvider untuk inisialisasi otomatis — tidak perlu mengubah kelas Application atau menambahkan kode di MainActivity. Koneksi dilakukan hanya untuk debug-build, agar tidak ada kode berlebih di APK rilis.
// build.gradle (app/module)
dependencies {
// debugImplementation — pustaka hanya untuk debug-build
debugImplementation "com.squareup.leakcanary:leakcanary-android:2.14"
}
Setelah menambahkan dependensi dan membangun ulang proyek, LeakCanary secara otomatis muncul di aplikasi. Pada peluncuran pertama, pustaka menampilkan notifikasi sistem tentang aktivasi. Semua kebocoran yang terdeteksi ditampilkan sebagai notifikasi — klik pada notifikasi membuka layar dengan laporan detail (LeakTrace).
Untuk kustomisasi, Anda dapat membuat AppWatcherInstaller sendiri dan menimpa parameter: batas waktu tunggu GC, daftar jenis objek yang dilacak, mengaktifkan penyimpanan heap dump ke disk. Namun, untuk 90% proyek, konfigurasi default sudah optimal.
Mulai dari versi 2.12, LeakCanary mendukung pelacakan otomatis ViewModel, scope coroutine, dan objek State Compose. Tidak diperlukan dependensi tambahan — pustaka sendiri mendeteksi komponen Jetpack mana yang digunakan dalam proyek dan mengaktifkan detektor yang sesuai.
Laporan LeakCanary (LeakTrace) — adalah rantai referensi multi-baris dari GC Root ke objek yang bocor. Setiap baris menunjukkan kelas dan field yang dilalui oleh referensi kuat. Pengembang harus membaca rantai dari bawah ke atas: baris bawah — objek yang bocor, baris atas — titik masuk (GC Root).
LeakTrace tipikal terlihat seperti ini: GC Root → field statis Application → singleton → callback → Activity. Jika pengembang melihat rantai seperti itu, masalahnya jelas: singleton menyimpan callback yang menangkap referensi ke Activity. Solusinya — ganti referensi kuat dengan referensi lemah di singleton.
┬
├─ android.app.Application
│ Leaking: NO (Application — singleton)
│ ↓ Application.leakedActivities
├─ java.util.ArrayList
│ Leaking: NO (ArrayList — normal)
│ ↓ ArrayList[0]
├─ com.example.MainActivity
│ Leaking: YES (Activity destroyed but still in memory)
│ ↓ MainActivity.mCallback
├─ com.example.CallbackWrapper
│ Leaking: UNKNOWN
│ ↓ CallbackWrapper.mListener
│ ~~~~~~~~~~
├─ com.example.MyCallback (anonymous)
│ Leaking: UNKNOWN
│ ↓ MyCallback.this$0
├─ com.example.MainActivity
│ Leaking: YES (MainActivity is the leak)
╰
Dalam contoh ini LeakCanary menunjukkan bahwa MainActivity ditahan melalui rantai: Application → ArrayList → MainActivity → CallbackWrapper → MyCallback → kembali ke MainActivity. Panah this$0 menunjukkan bahwa kelas anonim MyCallback menangkap referensi eksternal ke Activity. Solusinya — buat callback menjadi referensi lemah atau batalkan di onDestroy.
LeakCanary juga menunjukkan status kebocoran untuk setiap elemen rantai: NO (tidak ada kebocoran — ini elemen root), YES (objek harus dihancurkan), UNKNOWN (tidak dapat menentukan status). Status UNKNOWN tidak berarti masalah — ini adalah objek perantara yang tidak dapat diklasifikasikan secara jelas oleh LeakCanary.
Transisi dari versi 1.x ke 2.x bersifat radikal: pengembang menulis ulang pustaka dari awal, mengganti penganalisis HAHA yang sudah usang dengan mesin sendiri Shark yang ditulis dalam Kotlin. Shark bekerja jauh lebih cepat, membutuhkan lebih sedikit memori untuk analisis, dan menentukan akar penyebab kebocoran dengan lebih akurat.
| Parameter | LeakCanary 1.x | LeakCanary 2.x |
|---|---|---|
| Bahasa penganalisis | Java (HAHA — fork dari Android SDK) | Kotlin (Shark — mesin sendiri) |
| Instalasi | Konfigurasi manual AppWatcher di Application | Otomatis melalui ContentProvider |
| Kecepatan | 10–30 detik untuk analisis heap dump | 1–5 detik untuk analisis heap dump |
| Performa | Menggunakan 10–50 MB RAM saat analisis | Menggunakan 2–10 MB RAM saat analisis |
Keunggulan utama Shark — tidak memuat seluruh heap dump ke dalam memori, tetapi menelusuri grafik referensinya dengan alokasi minimal. Ini membuat LeakCanary 2.x cocok digunakan pada perangkat dengan RAM rendah tanpa risiko OutOfMemoryError selama analisis.
Di versi 2.x juga ditambahkan kemampuan untuk mengekspor heap dump ke file untuk analisis selanjutnya di Android Studio Memory Profiler. Untuk ini, aktifkan pengaturan dumpHeapWhenLeakFound di konfigurasi AppWatcher.
LeakCanary secara efektif mendeteksi beberapa kelas kebocoran yang khas untuk Android. Yang paling umum adalah kebocoran melalui referensi statis ke Activity — pengembang menyimpan referensi ke konteks Activity di singleton, dan Activity tidak dapat dikumpulkan oleh GC setelah siklus hidupnya selesai.
Kategori kedua yang paling sering — kebocoran melalui listener yang tidak terdaftar. Jika di onStart registerListener dipanggil, tetapi di onStop/onDestroy unregisterListener tidak dipanggil — objek listener ditahan oleh sistem bahkan setelah aktivitas dihancurkan. LeakCanary dengan jelas menunjukkan listener mana dan di layanan sistem mana yang tetap aktif.
// Kebocoran tipikal: Activity tertangkap dalam callback singleton
object AnalyticsManager {
private var callback: ((String) -> Unit)? = null
fun register(callback: (String) -> Unit) {
this.callback = callback // referensi kuat ke callback
}
fun unregister() {
callback = null // JANGAN LUPA panggil di onDestroy!
}
}
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
AnalyticsManager.register { event ->
logEvent(event) // lambda menangkap this
}
// jika tidak memanggil unregister di onDestroy → kebocoran Activity
}
}
Kategori ketiga — kebocoran melalui Fragment di BackStack. Jika FragmentTransaction.addToBackStack() dipanggil tanpa menghapus Fragment saat kembali, instance Fragment lama tetap di memori. LeakCanary membantu mendeteksi kebocoran tersembunyi seperti itu pada tahap awal pengembangan.
Untuk setiap kebocoran yang terdeteksi, LeakCanary menawarkan deskripsi dan rekomendasi perbaikan. Di versi 2.14, integrasi dengan Android Lint telah ditambahkan — pustaka dapat secara otomatis membuat tugas di issue tracker saat mendeteksi kebocoran di CI.
Pertanyaan yang Sering Diajukan
Ya, wajib. LeakCanary dihubungkan melalui debugImplementation di build.gradle, yang secara otomatis mengecualikannya dari build rilis. Jika Anda menghubungkannya melalui implementation, pustaka akan masuk ke APK rilis dan menampilkan kebocoran kepada pengguna akhir — ini tidak dapat diterima.
Dampak pada kinerja minimal. LeakCanary hanya aktif setelah onDestroy komponen dan tidak mengganggu rendering UI atau pemrosesan sentuhan. Satu-satunya biaya — jeda singkat GC paksa (sekitar 100 ms) dan penulisan heap dump saat kebocoran (seperseratus detik).
LeakCanary secara otomatis menyimpan heap dump dalam format HPROF di folder aplikasi. File dapat diekspor melalui Android Studio: Device File Explorer → data/data/com.example/files/leakcanary/. Untuk melihat, buka file di Memory Profiler melalui Capture → Open Heap Dump.
Ya, mulai dari versi 2.12 LeakCanary sepenuhnya mendukung Jetpack Compose. Pustaka melacak konteks Composition dan objek State, secara otomatis mendeteksi kebocoran di fungsi Composable. Konfigurasi terpisah tidak diperlukan — langsung berfungsi.
Positif palsu mungkin terjadi, tetapi jarang. LeakCanary menggunakan tiga kali panggilan GC sebelum menyatakan kebocoran, yang menghilangkan sebagian besar positif palsu. Jika Anda merasa pemicuannya palsu — buat IgnoredReference untuk kelas tertentu di konfigurasi.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga