LeakCanary — ano ito, library para sa paghahanap ng mga leak sa Android

May-akda: IT Sectr Nai-publish: 2026-03-30 Oras ng pagbabasa: 9 min

LeakCanary — ay isang open source library mula sa Square para sa awtomatikong pagtuklas ng mga memory leak sa mga Android application. Ito ay nagsasama sa proseso ng pag-develop at sa real-time ay sinusubaybayan ang lifecycle ng Activity, Fragment, ViewModel at iba pang mga component, na nagbibigay senyas ng mga leak kaagad pagkatapos mangyari ang mga ito. Ayon sa datos ng Square Open Source, ang library ay ginagamit sa libu-libong proyekto at itinuturing na de facto standard para sa memory diagnosis sa Android.

Mga Pangunahing Punto

  • LeakCanary — library para sa awtomatikong pagtuklas ng mga memory leak sa Android.
  • Mekanismo ng paggana ay batay sa WeakReference at manu-manong pagpapatakbo ng GC pagkatapos sirain ang component.
  • Heap dump ay awtomatikong nilikha kapag may nakitang leak at sinusuri ng built-in na analyzer.
  • Resulta — eksaktong chain ng mga reference (leak trace) na nagtuturo sa lokasyon ng leak sa code.
  • LeakCanary 2.x ay hindi nangangailangan ng manu-manong configuration — isang dependency sa build.gradle ay sapat na.

Ano ang LeakCanary?

LeakCanary — ay isang library para sa awtomatikong pagtuklas ng mga memory leak sa mga Android application, na binuo ng kumpanyang Square. Ito ay naka-embed sa proseso ng pagbuo ng application at awtomatikong sinusubaybayan kapag ang mga object na dapat sirain (Activity, Fragment, View) ay nananatili sa memory. Kapag may nakitang leak, ang LeakCanary ay gumagawa ng heap dump at sinusuri ang chain ng mga reference na humahawak sa object.

Ang library ay naging pamantayan sa komunidad ng Android: ayon sa datos ng GitHub, ang proyekto ay nakaipon ng mahigit 28 libong bituin at ginagamit sa mga application ng Google, Uber, Airbnb at Facebook. Ang LeakCanary ay available sa dalawang pangunahing bersyon: klasikong 1.x (na may manu-manong configuration) at modernong 2.x (awtomatikong integrasyon sa pamamagitan ng ContentProvider). Ang bersyon 2.x ay hindi nangangailangan ng pagbabago sa Application class — isang dependency ay sapat para sa buong paggana.

Ang pangunahing gawain ng LeakCanary ay tuklasin ang sitwasyon kung kailan ang isang object ay patuloy na umiiral sa memory pagkatapos makumpleto ang lifecycle nito. Ito ay tipikal para sa mga leak sa pamamagitan ng static na field, singleton, hindi rehistradong callback, anonymous na klase, at closure na kumukuha ng mga external na object.

Bakit mahalaga ang LeakCanary para sa pag-develop ng Android

Ang mga memory leak sa Android ay mas kritikal kaysa sa desktop dahil sa limitadong dami ng RAM sa mga mobile device. Kahit isang leak na 5–10 MB sa bawat paglipat ng screen ay maaaring humantong sa OutOfMemoryError pagkatapos ng 30–40 minutong paggamit ng application. Ang LeakCanary ay tumutuklas ng mga ganitong problema sa yugto ng pag-develop, hindi naghihintay ng pag-crash sa produksyon.

Paano gumagana ang LeakCanary?

LeakCanary ay gumagamit ng mahinang reference (WeakReference) kasama ng sapilitang pagtawag sa garbage collector. Kapag ang Activity o Fragment ay tumawag ng onDestroy, ang LeakCanary ay gumagawa ng WeakReference sa object na ito at pinapatakbo ang GC pagkatapos ng maikling pagkaantala (default na 5 segundo). Kung pagkatapos ng GC ang object ay maaari pa ring maabot sa pamamagitan ng WeakReference, nangangahulugan ito na ito ay hawak ng isang malakas na reference — isang leak ang naitala.

Pagkatapos matuklasan ang leak, ang LeakCanary ay gumagawa ng heap dump (kumpletong snapshot ng memory ng application sa HPROF format). Pagkatapos ang built-in na analyzer (Shark para sa bersyon 2.x) ay bumubuo ng graph ng reachability mula sa GC Roots hanggang sa tumagas na object at hinahanap ang pinakamaikling landas — ang chain ng mga reference na humahawak sa object sa memory.

kotlin
// Pinasimpleng logic ng detection ng LeakCanary
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() // sapilitang GC
        for (ref in watchedReferences) {
            if (ref.get() != null) {
                onLeakFound(ref) // nakaligtas ang object sa GC — ito ay leak
            }
        }
    }
}

Ang pangunahing punto — ang sapilitang pagtawag ng GcTrigger.runGc(). Kung wala ito, hindi posible na makilala ang isang object na talagang tumagas mula sa isang object na hindi pa nakokolekta ng GC. Ginagawa ito ng LeakCanary hanggang tatlong beses: kung pagkatapos ng tatlong GC cycle ang object ay nasa memory pa rin — ang leak ay nakumpirma.

Ano ang Shark — heap dump analyzer

Shark — ay ang built-in na heap dump analyzer sa LeakCanary 2.x, na isinulat sa Kotlin. Hindi tulad ng nakaraang analyzer na HAHA, hindi nilo-load ng Shark ang buong HPROF file sa memory, sa halip ay tinatahak nito ang graph ng object nito na may minimal na alokasyon. Binabawasan nito ang pagkonsumo ng RAM sa panahon ng pagsusuri mula 50 MB hanggang 2–5 MB at pinaikli ang oras ng pagsusuri mula 30 segundo hanggang 1–3 segundo.

Paano i-install at i-configure ang LeakCanary?

Ang pag-install ng LeakCanary 2.x sa isang modernong Android project ay tumatagal ng isang linya sa build.gradle. Ang library ay gumagamit ng ContentProvider para sa awtomatikong pagsisimula — hindi na kailangang baguhin ang Application class o magdagdag ng code sa MainActivity. Ang koneksyon ay ginagawa lamang para sa debug-build, upang walang labis na code sa release APK.

groovy
// build.gradle (app/module)
dependencies {
    // debugImplementation — library para lamang sa debug-build
    debugImplementation "com.squareup.leakcanary:leakcanary-android:2.14"
}

Pagkatapos idagdag ang dependency at muling buuin ang proyekto, ang LeakCanary ay awtomatikong lilitaw sa application. Sa unang pagtakbo, ang library ay nagpapakita ng system notification tungkol sa activation. Lahat ng nakitang leak ay ipinapakita bilang mga notification — ang pag-click sa notification ay nagbubukas ng screen na may detalyadong report (LeakTrace).

Para sa pagpapasadya, maaari kang gumawa ng sarili mong AppWatcherInstaller at i-override ang mga parameter: timeout ng paghihintay ng GC, listahan ng mga sinusubaybayang uri ng object, pag-enable ng pag-save ng heap dump sa disk. Gayunpaman, para sa 90% ng mga proyekto, ang default na configuration ay optimal.

Configuration para sa coroutine at Jetpack Compose

Simula sa bersyon 2.12, ang LeakCanary ay sumusuporta sa awtomatikong pagsubaybay ng ViewModel, coroutine scope, at State object ng Compose. Hindi kailangan ng karagdagang dependency — ang library mismo ang tumutukoy kung aling mga Jetpack component ang ginagamit sa proyekto at ina-activate ang mga kaukulang detector.

Paano basahin ang report ng LeakCanary

Ang report ng LeakCanary (LeakTrace) — ay isang multi-line chain ng mga reference mula sa GC Root hanggang sa tumagas na object. Bawat linya ay nagpapakita ng klase at field kung saan dumadaan ang malakas na reference. Dapat basahin ng developer ang chain mula sa ibaba pataas: ibabang linya — tumagas na object, itaas na linya — entry point (GC Root).

Ang karaniwang LeakTrace ay ganito ang hitsura: GC Root → static na field ng Application → singleton → callback → Activity. Kung ang developer ay nakakakita ng ganitong chain, malinaw ang problema: ang singleton ay humahawak ng callback na kumuha ng reference sa Activity. Solusyon — palitan ang malakas na reference ng mahina sa singleton.

text
┬
├─ 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)
╰

Sa halimbawang ito, ipinapakita ng LeakCanary na ang MainActivity ay hawak sa pamamagitan ng chain: Application → ArrayList → MainActivity → CallbackWrapper → MyCallback → bumalik sa MainActivity. Ang arrow na this$0 ay nagpapahiwatig na ang anonymous na klase na MyCallback ay kumuha ng external na reference sa Activity. Solusyon — gawing mahinang reference ang callback o kanselahin ito sa onDestroy.

Ipinapakita rin ng LeakCanary ang status ng leak para sa bawat elemento ng chain: NO (walang leak — ito ang root element), YES (dapat sirain ang object), UNKNOWN (hindi matukoy ang status). Ang status na UNKNOWN ay hindi nangangahulugang problema — ito ay isang intermediate na object na hindi malinaw na mauuri ng LeakCanary.

LeakCanary 2.x vs 1.x: mga pangunahing pagkakaiba

Ang paglipat mula sa bersyon 1.x patungo sa 2.x ay radikal: muling isinulat ng mga developer ang library mula sa simula, pinalitan ang lumang HAHA analyzer ng sariling engine na Shark na isinulat sa Kotlin. Ang Shark ay gumagana nang mas mabilis, nangangailangan ng mas kaunting memory para sa pagsusuri, at mas tumpak na tinutukoy ang mga ugat na sanhi ng mga leak.

ParameterLeakCanary 1.xLeakCanary 2.x
Wika ng analyzerJava (HAHA — fork ng Android SDK)Kotlin (Shark — sariling engine)
Pag-installManu-manong configuration ng AppWatcher sa ApplicationAwtomatiko sa pamamagitan ng ContentProvider
Bilis10–30 segundo para sa pagsusuri ng heap dump1–5 segundo para sa pagsusuri ng heap dump
PagganapGumagamit ng 10–50 MB RAM sa panahon ng pagsusuriGumagamit ng 2–10 MB RAM sa panahon ng pagsusuri

Ang pangunahing bentahe ng Shark — hindi nito nilo-load ang buong heap dump sa memory, sa halip ay tinatahak ang reference graph nito na may minimal na alokasyon. Ginagawa nitong angkop ang LeakCanary 2.x para sa paggamit sa mga device na may mababang RAM nang walang panganib ng OutOfMemoryError sa panahon ng pagsusuri.

Sa bersyon 2.x ay idinagdag din ang kakayahang i-export ang heap dump sa isang file para sa karagdagang pagsusuri sa Android Studio Memory Profiler. Para dito, kailangan i-enable ang setting na dumpHeapWhenLeakFound sa configuration ng AppWatcher.

Mga karaniwang leak na natagpuan ng LeakCanary

LeakCanary ay epektibong tumutuklas ng ilang klase ng mga leak na katangian ng Android. Ang pinakakaraniwan ay ang leak sa pamamagitan ng static na reference sa Activity — ang mga developer ay nag-iimbak ng reference sa konteksto ng Activity sa isang singleton, at ang Activity ay hindi makokolekta ng GC pagkatapos makumpleto ang lifecycle nito.

Ang pangalawang pinakakaraniwang kategorya — mga leak sa pamamagitan ng hindi rehistradong listener. Kung sa onStart ay tinawag ang registerListener, ngunit sa onStop/onDestroy ay hindi tinawag ang unregisterListener — ang object-listener ay hawak ng system kahit pagkatapos sirain ang activity. Ang LeakCanary ay malinaw na nagpapakita kung aling listener at sa aling system service ang nanatiling aktibo.

kotlin
// Karaniwang leak: Activity nahuli sa callback ng singleton
object AnalyticsManager {
    private var callback: ((String) -> Unit)? = null

    fun register(callback: (String) -> Unit) {
        this.callback = callback // malakas na reference sa callback
    }

    fun unregister() {
        callback = null // HUWAG KALIMUTANG tawagin sa onDestroy!
    }
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        AnalyticsManager.register { event ->
            logEvent(event) // lambda ay kumukuha ng this
        }
        // kung hindi tatawagin ang unregister sa onDestroy → leak ng Activity
    }
}

Ang ikatlong kategorya — mga leak sa pamamagitan ng Fragment sa BackStack. Kung ang FragmentTransaction.addToBackStack() ay tinawag nang hindi tinatanggal ang Fragment sa pagbabalik, ang mga lumang instance ng Fragment ay nananatili sa memory. Ang LeakCanary ay tumutulong na matuklasan ang mga nakatagong leak na ito sa mga unang yugto ng pag-develop.

Para sa bawat nakitang leak, ang LeakCanary ay nag-aalok ng paglalarawan at mga rekomendasyon para sa pag-aayos. Sa bersyon 2.14, idinagdag ang integrasyon sa Android Lint — ang library ay maaaring awtomatikong lumikha ng mga task sa issue tracker kapag may nakitang leak sa CI.

Mga Madalas Itanong

Kailangan bang tanggalin ang LeakCanary mula sa release APK?

Oo, kinakailangan. Ang LeakCanary ay ikinokonekta sa pamamagitan ng debugImplementation sa build.gradle, na awtomatikong nagbubukod nito mula sa release build. Kung ikinonekta mo ito sa pamamagitan ng implementation, ang library ay mapupunta sa release APK at magpapakita ng mga leak sa mga end user — ito ay hindi katanggap-tanggap.

Pinapabagal ba ng LeakCanary ang paggana ng application?

Ang epekto sa pagganap ay minimal. Ang LeakCanary ay naa-activate lamang pagkatapos ng onDestroy ng component at hindi nakikialam sa rendering ng UI o pagproseso ng pagpindot. Ang tanging gastos — maikling paghinto ng sapilitang GC (mga 100 ms) at pagsulat ng heap dump sa leak (daang bahagi ng segundo).

Paano i-export ang report ng LeakCanary?

Ang LeakCanary ay awtomatikong nagse-save ng heap dump sa HPROF format sa folder ng application. Ang file ay maaaring i-export sa pamamagitan ng Android Studio: Device File Explorer → data/data/com.example/files/leakcanary/. Para matingnan, buksan ang file sa Memory Profiler sa pamamagitan ng Capture → Open Heap Dump.

Gumagana ba ang LeakCanary sa Jetpack Compose?

Oo, simula sa bersyon 2.12 ang LeakCanary ay ganap na sumusuporta sa Jetpack Compose. Sinusubaybayan ng library ang mga konteksto ng Composition at mga State object, awtomatikong tumutuklas ng mga leak sa mga Composable function. Hindi kailangan ng hiwalay na configuration — gumagana ito agad.

Maaari bang magkamali ang LeakCanary (false positive)?

Ang mga maling pag-activate ay posible, ngunit bihira. Gumagamit ang LeakCanary ng tatlong beses na pagtawag ng GC bago magpahayag ng leak, na nag-aalis ng karamihan sa mga false positive. Kung sa tingin mo ay mali ang pag-activate — gumawa ng IgnoredReference para sa partikular na klase sa configuration.

Buod

  • LeakCanary — pamantayang library para sa awtomatikong pagtuklas ng mga memory leak sa Android application.
  • Ang library ay gumagamit ng WeakReference at sapilitang GC para sa pagtuklas ng mga object na nakaligtas sa kanilang lifecycle.
  • Heap dump ay sinusuri ng built-in na Shark engine, na bumubuo ng chain ng mga reference mula sa GC Root hanggang sa tumagas na object.
  • Pag-install sa modernong proyekto — isang linya sa build.gradle: debugImplementation.
  • Ang LeakCanary 2.x ay ganap na muling isinulat sa Kotlin at gumagana nang 5–10 beses na mas mabilis kaysa sa nakaraang bersyon.
  • Mga pinakakaraniwang leak: static na reference sa Activity, hindi rehistradong listener, at Fragment sa BackStack.
  • Ipatupad ang LeakCanary sa debug-build ng bawat proyekto — ito ay makakapigil sa mga leak sa produksyon.

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din