LeakCanary — cos'è, libreria per trovare perdite in Android

Autore: IT Sectr Pubblicato: 2026-03-30 Tempo di lettura: 9 min

LeakCanary è una libreria open source di Square per il rilevamento automatico di perdite di memoria nelle applicazioni Android. Si integra nel processo di sviluppo e monitora in tempo reale il ciclo di vita di Activity, Fragment, ViewModel e altri componenti, segnalando le perdite non appena si verificano. Secondo Square Open Source, la libreria è utilizzata in migliaia di progetti ed è considerata lo standard de facto per la diagnostica della memoria su Android.

Punti chiave

  • LeakCanary è una libreria per il rilevamento automatico di perdite di memoria su Android.
  • Meccanismo di funzionamento basato su WeakReference e attivazione manuale del GC dopo la distruzione del componente.
  • Heap dump viene creato automaticamente quando viene rilevata una perdita e analizzato dall'analizzatore integrato.
  • Risultato — una catena di riferimenti esatta (leak trace) che indica la posizione della perdita nel codice.
  • LeakCanary 2.x non richiede configurazione manuale — basta una dipendenza in build.gradle.

Cos'è LeakCanary?

LeakCanary è una libreria per il rilevamento automatico di perdite di memoria nelle applicazioni Android, sviluppata da Square. Si integra nel processo di build dell'app e monitora automaticamente se gli oggetti che dovrebbero essere distrutti (Activity, Fragment, View) rimangono in memoria. Quando viene rilevata una perdita, LeakCanary genera un heap dump e analizza la catena di riferimenti che trattiene l'oggetto.

La libreria è diventata uno standard nella comunità Android: secondo GitHub, il progetto ha oltre 28 mila stelle ed è utilizzato nelle applicazioni di Google, Uber, Airbnb e Facebook. LeakCanary è disponibile in due versioni principali: la classica 1.x (con configurazione manuale) e la moderna 2.x (integrazione automatica tramite ContentProvider). La versione 2.x non richiede la modifica della classe Application — la dipendenza è sufficiente per il funzionamento completo.

Il compito principale di LeakCanary è rilevare quando un oggetto continua a esistere in memoria dopo la fine del suo ciclo di vita. Questo è tipico delle perdite attraverso campi statici, singleton, callback non deregistrati, classi anonime e closure che catturano oggetti esterni.

Perché LeakCanary è importante per lo sviluppo Android

Le perdite di memoria su Android sono più critiche che sul desktop a causa della RAM limitata dei dispositivi mobili. Anche una perdita di 5–10 MB a ogni transizione di schermata può portare a un OutOfMemoryError dopo 30–40 minuti di utilizzo dell'app. LeakCanary rileva questi problemi nella fase di sviluppo, senza aspettare un crash in produzione.

Come funziona LeakCanary?

LeakCanary utilizza riferimenti deboli (WeakReference) combinati con garbage collection forzata. Quando un'Activity o un Fragment chiama onDestroy, LeakCanary crea un WeakReference su quell'oggetto e attiva il GC dopo un breve ritardo (5 secondi per impostazione predefinita). Se l'oggetto è ancora accessibile tramite WeakReference dopo il GC, viene trattenuto da un riferimento forte — viene registrata una perdita.

Dopo aver rilevato una perdita, LeakCanary esegue un heap dump (dump della memoria) — un'istantanea completa della memoria dell'app in formato HPROF. Quindi l'analizzatore integrato (Shark per la versione 2.x) costruisce un grafo di raggiungibilità dalle GC Roots all'oggetto perso e trova il percorso più breve — la catena di riferimenti che mantiene l'oggetto in memoria.

kotlin
// Logica semplificata di rilevamento di 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() // GC forzato
        for (ref in watchedReferences) {
            if (ref.get() != null) {
                onLeakFound(ref) // l'oggetto è sopravvissuto al GC — è una perdita
            }
        }
    }
}

Il punto chiave è la chiamata forzata a GcTrigger.runGc(). Senza di essa, è impossibile distinguere un oggetto che è effettivamente perso da uno che il GC non ha ancora raccolto. LeakCanary lo fa fino a tre volte: se dopo tre cicli di GC l'oggetto è ancora in memoria, la perdita è confermata.

Cos'è Shark — l'analizzatore di heap dump

Shark è l'analizzatore di heap dump integrato in LeakCanary 2.x, scritto in Kotlin. A differenza del precedente analizzatore HAHA, Shark non carica l'intero file HPROF in memoria, ma attraversa il suo grafo di oggetti con allocazioni minime. Ciò riduce il consumo di RAM durante l'analisi da 50 MB a 2–5 MB e accorcia il tempo di analisi da 30 secondi a 1–3 secondi.

Come installare e configurare LeakCanary?

Installare LeakCanary 2.x in un progetto Android moderno richiede una riga in build.gradle. La libreria utilizza ContentProvider per l'inizializzazione automatica — non è necessario modificare la classe Application né aggiungere codice a MainActivity. La dipendenza viene aggiunta solo per le build debug, in modo che gli APK di rilascio non contengano codice extra.

groovy
// build.gradle (app/module)
dependencies {
    // debugImplementation — libreria solo per build debug
    debugImplementation "com.squareup.leakcanary:leakcanary-android:2.14"
}

Dopo aver aggiunto la dipendenza e ricostruito il progetto, LeakCanary appare automaticamente nell'app. Al primo avvio, la libreria mostra una notifica di sistema che conferma l'attivazione. Tutte le perdite rilevate appaiono come notifiche — toccando una notifica si apre una schermata con un report dettagliato (LeakTrace).

Per la personalizzazione, puoi creare il tuo AppWatcherInstaller e sovrascrivere i parametri: timeout GC, elenco dei tipi di oggetti tracciati, abilitazione del salvataggio dell'heap dump su disco. Tuttavia, per il 90% dei progetti, la configurazione predefinita è ottimale.

Configurazione per coroutine e Jetpack Compose

A partire dalla versione 2.12, LeakCanary supporta il tracciamento automatico di ViewModel, ambiti delle coroutine e oggetti State di Compose. Non sono necessarie dipendenze aggiuntive — la libreria rileva automaticamente quali componenti Jetpack sono utilizzati nel progetto e attiva i relativi rilevatori.

Come leggere un report di LeakCanary

Un report di LeakCanary (LeakTrace) è una catena di riferimenti a più righe dalla GC Root all'oggetto perso. Ogni riga mostra la classe e il campo attraverso cui passa un riferimento forte. Lo sviluppatore deve leggere la catena dal basso verso l'alto: la riga inferiore è l'oggetto perso, la riga superiore è il punto di ingresso (GC Root).

Un LeakTrace tipico appare così: GC Root → campo statico di Application → singleton → callback → Activity. Se uno sviluppatore vede questa catena, il problema è chiaro: il singleton trattiene un callback che ha catturato un riferimento all'Activity. La soluzione è sostituire il riferimento forte con uno debole nel 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)
╰

In questo esempio, LeakCanary mostra che MainActivity è trattenuta attraverso la catena: Application → ArrayList → MainActivity → CallbackWrapper → MyCallback → di nuovo MainActivity. La freccia this$0 indica che la classe anonima MyCallback ha catturato un riferimento esterno all'Activity. La soluzione è rendere il callback un riferimento debole o cancellarlo in onDestroy.

LeakCanary mostra anche lo stato della perdita per ogni elemento della catena: NO (nessuna perdita — elemento radice), YES (l'oggetto dovrebbe essere distrutto), UNKNOWN (stato indeterminato). Lo stato UNKNOWN non significa un problema — è un oggetto intermedio che LeakCanary non può classificare in modo definitivo.

LeakCanary 2.x vs 1.x: differenze chiave

Il passaggio dalla versione 1.x alla 2.x è stato radicale: gli sviluppatori hanno riscritto la libreria da zero, sostituendo il vecchio analizzatore HAHA con il proprio motore Shark, scritto in Kotlin. Shark è un ordine di grandezza più veloce, richiede meno memoria per l'analisi e determina con maggiore precisione le cause profonde delle perdite.

ParametroLeakCanary 1.xLeakCanary 2.x
Linguaggio analizzatoreJava (HAHA — fork dell'Android SDK)Kotlin (Shark — motore proprietario)
InstallazioneConfigurazione manuale di AppWatcher in ApplicationAutomatica tramite ContentProvider
Velocità10–30 secondi per l'analisi dell'heap dump1–5 secondi per l'analisi dell'heap dump
PrestazioniConsuma 10–50 MB di RAM durante l'analisiConsuma 2–10 MB di RAM durante l'analisi

Il vantaggio chiave di Shark è che non carica l'intero heap dump in memoria, ma attraversa il suo grafo di riferimenti con allocazioni minime. Questo rende LeakCanary 2.x utilizzabile su dispositivi con poca RAM senza il rischio di OutOfMemoryError durante l'analisi.

La versione 2.x ha anche introdotto la possibilità di esportare gli heap dump in un file per l'analisi successiva in Android Studio Memory Profiler. Per farlo, attiva l'impostazione dumpHeapWhenLeakFound nella configurazione di AppWatcher.

Perdite tipiche trovate da LeakCanary

LeakCanary rileva efficacemente diverse classi di perdite comuni in Android. La più frequente è la perdita attraverso riferimenti statici a un'Activity — gli sviluppatori mantengono un riferimento al contesto dell'Activity in un singleton, e l'Activity non può essere raccolta dal GC dopo la fine del suo ciclo di vita.

La seconda categoria più comune sono le perdite attraverso listener non deregistrati. Se registerListener è stato chiamato in onStart ma unregisterListener non è stato chiamato in onStop/onDestroy, l'oggetto listener viene trattenuto dal sistema anche dopo la distruzione dell'attività. LeakCanary mostra chiaramente quale listener e in quale servizio di sistema rimane vivo.

kotlin
// Perdita tipica: Activity catturata in un callback di singleton
object AnalyticsManager {
    private var callback: ((String) -> Unit)? = null

    fun register(callback: (String) -> Unit) {
        this.callback = callback // riferimento forte al callback
    }

    fun unregister() {
        callback = null // NON DIMENTICARE di chiamare in onDestroy!
    }
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        AnalyticsManager.register { event ->
            logEvent(event) // lambda cattura this
        }
        // se unregister non viene chiamato in onDestroy → perdita di Activity
    }
}

La terza categoria sono le perdite attraverso Fragment nel BackStack. Se FragmentTransaction.addToBackStack() viene chiamato senza rimuovere il Fragment durante il ritorno, le vecchie istanze di Fragment rimangono in memoria. LeakCanary aiuta a rilevare queste perdite nascoste nelle prime fasi dello sviluppo.

Per ogni perdita rilevata, LeakCanary fornisce una descrizione e raccomandazioni per la correzione. La versione 2.14 ha aggiunto l'integrazione con Android Lint — la libreria può creare automaticamente attività nel tracker dei problemi quando viene rilevata una perdita in CI.

Domande frequenti

È necessario rimuovere LeakCanary dall'APK di rilascio?

Sì, assolutamente. LeakCanary viene aggiunto tramite debugImplementation in build.gradle, che lo esclude automaticamente dalle build di rilascio. Se si utilizza implementation, la libreria verrà inclusa nell'APK di rilascio e mostrerà le perdite agli utenti finali — questo è inaccettabile.

LeakCanary rallenta l'applicazione?

L'impatto sulle prestazioni è minimo. LeakCanary si attiva solo dopo l'onDestroy del componente e non interferisce con il rendering dell'interfaccia o la gestione dei tocchi. L'unico costo è una breve pausa forzata del GC (circa 100 ms) e la scrittura dell'heap dump quando si verifica una perdita (frazioni di secondo).

Come esportare un report di LeakCanary?

LeakCanary salva automaticamente gli heap dump in formato HPROF nella cartella dell'app. Il file può essere esportato tramite Android Studio: Device File Explorer → data/data/com.example/files/leakcanary/. Per visualizzarlo, apri il file in Memory Profiler tramite Capture → Open Heap Dump.

LeakCanary funziona con Jetpack Compose?

Sì, a partire dalla versione 2.12 LeakCanary supporta completamente Jetpack Compose. La libreria traccia i contesti di Composition e gli oggetti State, rilevando automaticamente le perdite nelle funzioni Composable. Non è necessaria una configurazione separata — funziona immediatamente.

LeakCanary può produrre falsi positivi?

I falsi positivi sono possibili ma rari. LeakCanary utilizza una triplice chiamata al GC prima di dichiarare una perdita, eliminando la maggior parte dei falsi positivi. Se ritieni che un rilevamento sia un falso positivo, crea un IgnoredReference per la classe specifica nella configurazione.

Riepilogo

  • LeakCanary è la libreria standard per il rilevamento automatico di perdite di memoria nelle applicazioni Android.
  • La libreria utilizza WeakReference e GC forzato per rilevare gli oggetti che sopravvivono al loro ciclo di vita.
  • Heap dump analizzato dal motore Shark integrato, che costruisce una catena di riferimenti dalla GC Root all'oggetto perso.
  • Installazione in un progetto moderno: una riga in build.gradle: debugImplementation.
  • LeakCanary 2.x è completamente riscritto in Kotlin e funziona 5–10 volte più velocemente della versione precedente.
  • Perdite più comuni: riferimenti statici ad Activity, listener non deregistrati e Fragment nel BackStack.
  • Aggiungi LeakCanary alla build debug di ogni progetto — previene le perdite in produzione.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche