Acquisisci un dump dell'heap

Acquisisci un dump dell'heap per vedere quali oggetti della tua app utilizzano la memoria al momento dell'acquisizione e identificare perdite di memoria o comportamenti di allocazione della memoria che causano stuttering, blocchi e persino arresti anomali dell'app. È particolarmente utile acquisire dump dell'heap dopo una sessione utente prolungata, quando potrebbero mostrare oggetti ancora in memoria che non dovrebbero più essere presenti.

Questa pagina descrive gli strumenti forniti da Android Studio per raccogliere e analizzare i dump dell'heap. In alternativa, puoi ispezionare la memoria dell'app dalla riga di comando con dumpsys e anche visualizzare gli eventi di garbage collection (GC) in Logcat.

Perché dovresti profilare la memoria della tua app

Android fornisce un ambiente di memoria gestita: quando Android determina che la tua app non utilizza più alcuni oggetti, il garbage collector rilascia la memoria inutilizzata nell'heap. Il modo in cui Android trova la memoria inutilizzata viene costantemente migliorato, ma a un certo punto, su tutte le versioni di Android, il sistema deve mettere brevemente in pausa il codice. La maggior parte delle volte, le pause sono impercettibili. Tuttavia, se la tua app alloca la memoria più velocemente di quanto il sistema possa raccoglierla, potrebbe subire ritardi mentre il raccoglitore libera memoria sufficiente per soddisfare le tue allocazioni. Il ritardo potrebbe causare la perdita di frame da parte dell'app e una lentezza visibile.

Anche se la tua app non mostra lentezza, se perde memoria, può conservarla anche quando è in background. Questo comportamento può rallentare le prestazioni della memoria del resto del sistema forzando eventi di garbage collection non necessari. Alla fine, il sistema è costretto a terminare il processo dell'app per recuperare la memoria. Quando l'utente torna alla tua app, il processo dell'app deve riavviarsi completamente.

Per informazioni sulle pratiche di programmazione che possono ridurre l'utilizzo della memoria della tua app, leggi [Gestisci la memoria della tua app]memory.

Panoramica del dump dell'heap

Per acquisire un dump dell'heap, seleziona l'attività Analizza la memoria utilizzata (dump dell'heap) (utilizza Profiler: esegui "app" come abilitato al debug (dati completi)) per acquisire un dump dell'heap. Durante il dump dell'heap, la quantità di memoria Java potrebbe aumentare temporaneamente. Questo è normale perché il dump dell'heap si verifica nello stesso processo della tua app e richiede un po' di memoria per raccogliere i dati. Dopo aver acquisito il dump dell'heap, vedrai quanto segue:

La visualizzazione dump dell'heap in Android Studio Profiler.

L'elenco dei corsi mostra le seguenti informazioni:

  • Allocazioni: numero di allocazioni nell'heap.
  • Dimensione nativa: quantità totale di memoria nativa utilizzata da questo tipo di oggetto (in byte). Qui vedrai la memoria per alcuni oggetti allocati in Java perché Android utilizza la memoria nativa per alcune classi del framework, ad esempio Bitmap.

  • Dimensione di base: quantità totale di memoria Java utilizzata da questo tipo di oggetto (in byte).

  • Dimensione mantenuta: dimensione totale della memoria mantenuta a causa di tutte le istanze di questa classe (in byte).

Utilizza il menu degli heap per filtrare in base a determinati heap:

  • Heap dell'app (predefinito): l'heap principale su cui l'app alloca la memoria.
  • Heap immagine: l'immagine di avvio del sistema, contenente le classi precaricate durante l'avvio. Le allocazioni qui non vengono mai spostate o rimosse.
  • Heap zygote: l'heap copy-on-write da cui viene eseguito il fork di un processo dell'app nel sistema Android.

Utilizza il menu a discesa Disposizione per scegliere come disporre le allocazioni:

  • Disponi per classe (impostazione predefinita): raggruppa tutte le allocazioni in base al nome della classe.
  • Disponi per pacchetto: raggruppa tutte le allocazioni in base al nome del pacchetto.

Utilizza il menu a discesa dei corsi per filtrare i gruppi di corsi:

  • Tutte le classi (impostazione predefinita): mostra tutte le classi, incluse quelle delle librerie e delle dipendenze.
  • Mostra perdite di attività/frammenti: mostra le classi che causano perdite di memoria.
  • Mostra classi del progetto: mostra solo le classi definite dal progetto.

Fai clic sul nome di una classe per aprire il riquadro Istanza. Ogni istanza elencata include:

  • Profondità: il numero più basso di hop da qualsiasi radice GC all'istanza selezionata.
  • Dimensione nativa: dimensione di questa istanza nella memoria nativa. Questa colonna è visibile solo per Android 7.0 e versioni successive.
  • Dimensione di base: dimensione di questa istanza nella memoria Java.
  • Dimensione mantenuta: dimensione della memoria dominata da questa istanza (in base all'albero dominatore).

Fai clic su un'istanza per visualizzare i Dettagli istanza, inclusi i relativi Campi e Riferimenti. I tipi di campi e riferimenti comuni sono tipi strutturati , array e tipi di dati primitivi in Java. Fai clic con il tasto destro del mouse su un campo o un riferimento per andare all'istanza o alla riga associata nel codice sorgente.

  • Campi: mostra tutti i campi di questa istanza.
  • Riferimenti: mostra ogni riferimento all'oggetto evidenziato nella scheda Istanza.
Le visualizzazioni Istanze, Campi e Riferimenti nella finestra dello strumento dump dell'heap.

Rileva bitmap duplicate

Puoi anche rilevare bitmap ridondanti nella visualizzazione dump dell'heap a partire da Android Studio Narwhal 4.

Ecco come trovarli:

  1. Apri la scheda Profiler in Android Studio
  2. Fai clic su dump dell'heap (o memoria utilizzata) e poi su Registra per acquisire un'istantanea dello stato attuale della memoria dell'app.
  3. Cerca nei risultati dell'analisi il triangolo di avviso giallo ⚠️, che Android Studio utilizza per segnalare le bitmap duplicate archiviate più volte.
    • In alternativa, vai all'intestazione del profiler, scegli Filtra per: e seleziona l'impostazione Bitmap duplicate.
  4. Fai clic su una voce segnalata per aprire il riquadro Anteprima bitmap, che ti consente di vedere esattamente quale immagine è l'autore della violazione ripetuta.
  5. Utilizza questa conferma visiva per rintracciare la logica di caricamento ridondante nel codice e implementare una strategia di memorizzazione nella cache migliore.
Cerca bitmap duplicate utilizzando il triangolo di avviso giallo ⚠️.

Trova le perdite di memoria

Per filtrare rapidamente le classi che potrebbero essere associate a perdite di memoria, apri il menu a discesa delle classi e seleziona Mostra perdite di attività/frammenti. Android Studio mostra le classi che ritiene indichino perdite di memoria per le istanze Activity e Fragment nella tua app.

Per cercare le perdite di memoria in modo più manuale, sfoglia gli elenchi di classi e istanze per trovare oggetti con una dimensione mantenuta elevata. Cerca perdite di memoria causate da uno dei seguenti fattori:

  • Riferimenti di lunga durata a Activity o Context che possono causare la perdita del grafico di composizione di Compose ospitato (ad esempio ComposeView e i relativi elementi componibili secondari).
  • Perdita di oggetti State di Jetpack Compose (MutableState), contenitori di stato o lambda che acquisiscono Context.
  • Dimenticare di pulire i listener o gli osservatori nel blocco onDispose di un DisposableEffect.
  • Classi interne non statiche, come Runnable, che possono contenere un'istanza Activity.
  • Cache che conservano gli oggetti più a lungo del necessario.

Quando trovi potenziali perdite di memoria, utilizza le schede Campi e Riferimenti in Dettagli istanza per passare all'istanza o alla riga di codice sorgente di interesse.

Attiva perdite di memoria per i test

Per analizzare la memoria utilizzata, devi sottoporre a stress il codice dell'app e provare a forzare le perdite di memoria. Un modo per provocare perdite di memoria nella tua app è lasciarla in esecuzione per un po' prima di ispezionare l'heap. Le perdite potrebbero arrivare fino alla parte superiore delle allocazioni nell'heap. Tuttavia, minore è la perdita, più a lungo dovrai eseguire l'app per vederla.

Puoi anche attivare una perdita di memoria in uno dei seguenti modi:

  • Ruota il dispositivo dalla modalità verticale a quella orizzontale e viceversa più volte mentre si trova in stati di attività diversi. La rotazione del dispositivo può spesso causare un leak di un Activity (e di conseguenza dell'albero della UI di Compose ospitato e degli alberi di stato associati) se l'app contiene un riferimento a Activity o Context all'interno di operazioni asincrone o contenitori di stato.
  • Passa dalla tua app a un'altra app mentre si trovano in stati di attività diversi. Ad esempio, vai alla schermata Home e poi torna all'app.

Esporta e importa una registrazione di dump dell'heap

Puoi esportare e importare un file di dump dell'heap dalla scheda Registrazioni precedenti del profiler. Android Studio salva la registrazione come file .hprof.

In alternativa, per utilizzare un analizzatore di file .hprof diverso come jhat, devi convertire il file .hprof dal formato Android al formato file .hprof Java SE. Per convertire il formato file, utilizza lo strumento hprof-conv fornito nella directory {android_sdk}/platform-tools/. Esegui il comando hprof-conv con due argomenti: il nome file .hprof originale e la posizione in cui scrivere il file .hprof convertito, incluso il nuovo nome file .hprof. Ad esempio:

hprof-conv heap-original.hprof heap-converted.hprof

Risorse aggiuntive