Ispeziona la memoria utilizzata dalla tua app con Memory Profiler

Memory Profiler è un componente di Android Profiler che ti aiuta a identificare le perdite di memoria e il tasso di abbandono della memoria che possono causare interruzioni, blocchi e persino arresti anomali dell'app. Mostra un grafico in tempo reale dell'utilizzo della memoria dell'app e ti consente di acquisire un dump dell'heap, forzare garbage collection e monitorare le allocazioni della memoria.

Per aprire Memory Profiler, procedi nel seguente modo:

  1. Fai clic su Visualizza > Finestre degli strumenti > Profiler (puoi anche fare clic su Profilo nella barra degli strumenti).
  2. Seleziona il processo del dispositivo e dell'app che vuoi profilare dalla barra degli strumenti di Android Profiler. Se il dispositivo che hai collegato tramite USB non appare nell'elenco, assicurati di aver attivato il debug USB.
  3. Fai clic in un punto qualsiasi della sequenza temporale MEMORY per aprire Memory Profiler.

In alternativa, puoi esaminare la memoria dell'app dalla riga di comando con dumpsys e anche visualizzare gli eventi GC in logcat.

Perché dovresti profilare la memoria dell'app

Android fornisce un ambiente di memoria gestito: quando 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 in pausa brevemente il codice. Il più delle volte, le pause sono impercettibili. Tuttavia, se la tua app alloca la memoria più velocemente di quanto il sistema può raccoglierla, l'app potrebbe subire ritardi mentre il raccoglitore libera memoria sufficiente per soddisfare le tue allocazioni. Il ritardo potrebbe far sì che l'app salti dei frame e causare lentezza visibile.

Anche se la tua app non presenta lentezza, in caso di perdita di memoria, può conservarla anche mentre è in background. Questo comportamento può rallentare il resto delle prestazioni della memoria del sistema, forzando eventi di garbage collection non necessari. Alla fine, il sistema è costretto a terminare il processo dell'app per recuperare memoria. Quando l'utente torna alla tua app, questa deve essere riavviata completamente.

Per evitare questi problemi, devi utilizzare Memory Profiler per:

  • Cerca modelli indesiderati di allocazione della memoria nella sequenza temporale che potrebbero causare problemi di prestazioni.
  • Esegui il dump dell'heap Java per vedere quali oggetti stanno consumando memoria in un determinato momento. Diversi dump dell'heap in un periodo di tempo prolungato possono aiutarti a identificare le perdite di memoria.
  • Registra le allocazioni della memoria durante un'interazione utente normale ed estrema per identificare esattamente dove il tuo codice sta allocando troppi oggetti in un breve periodo di tempo o allocando oggetti che sono divulgati.

Per informazioni sulle pratiche di programmazione che possono ridurre l'utilizzo della memoria dell'app, consulta Gestire la memoria dell'app.

Panoramica di Memory Profiler

Alla prima apertura di Memory Profiler, viene visualizzata una sequenza temporale dettagliata dell'utilizzo della memoria dell'app e degli strumenti di accesso per forzare la garbage collection, acquisire un dump dell'heap e registrare le allocazioni della memoria.

Figura 1. Memory Profiler

Come indicato nella Figura 1, la visualizzazione predefinita per Memory Profiler include quanto segue:

  1. Un pulsante per forzare un evento di garbage collection.
  2. Un pulsante per acquisire un dump dell'heap.

    Nota:a destra del pulsante di dump dell'heap viene visualizzato un pulsante per registrare le allocazioni della memoria soltanto se è attiva la connessione a un dispositivo con Android 7.1 (livello API 25) o versioni precedenti.

  3. Un menu a discesa per specificare la frequenza con cui il profiler acquisisce le allocazioni della memoria. La selezione dell'opzione appropriata potrebbe aiutarti a migliorare le prestazioni dell'app durante la profilazione.
  4. Pulsanti per lo zoom in avanti e indietro della sequenza temporale.
  5. Un pulsante per passare ai dati della memoria in tempo reale.
  6. La sequenza temporale degli eventi, che mostra gli stati delle attività, gli eventi di input utente e gli eventi di rotazione dello schermo.
  7. La sequenza temporale di utilizzo della memoria, che include quanto segue:
    • Un grafico in pila che mostra la quantità di memoria utilizzata da ogni categoria di memoria, come indicato dall'asse y a sinistra e dalla chiave colorata in alto.
    • Una linea tratteggiata indica il numero di oggetti allocati, come indicato dall'asse y a destra.
    • Un'icona per ogni evento di garbage collection.

Tuttavia, se utilizzi un dispositivo con Android 7.1 o versioni precedenti, non tutti i dati di profilazione sono visibili per impostazione predefinita. Se visualizzi il messaggio "La profilazione avanzata non è disponibile per il processo selezionato", devi abilitare la profilazione avanzata per visualizzare quanto segue:

  • Cronologia degli eventi
  • Numero di oggetti allocati
  • Eventi di raccolta dei rifiuti

Su Android 8.0 e versioni successive, la profilazione avanzata è sempre abilitata per le app di cui è possibile eseguire il debug.

Modalità di calcolo della memoria

I numeri che vedi nella parte superiore di Memory Profiler (figura 2) si basano su tutte le pagine di memoria private di cui la tua app ha eseguito il commit, secondo il sistema Android. Questo conteggio non include le pagine condivise con il sistema o con altre app.

Figura 2. La legenda del conteggio della memoria nella parte superiore di Memory Profiler

Le categorie nel conteggio della memoria sono le seguenti:

  • Java: memoria di oggetti allocati da codice Java o Kotlin.
  • Nativa: memoria degli oggetti allocati da codice C o C++.

    Anche se non usi C++ nella tua app, potresti notare che qui viene utilizzata una certa memoria nativa, perché il framework Android la usa per gestire varie attività per tuo conto, ad esempio per la gestione di asset immagine e altri elementi grafici, anche se il codice che hai scritto è in Java o Kotlin.

  • Elementi grafici: memoria utilizzata per le code di buffer grafici per visualizzare i pixel sullo schermo, incluse superfici GL, texture GL e così via. Tieni presente che si tratta di memoria condivisa con la CPU, non di memoria GPU dedicata.

  • Stack: memoria utilizzata dagli stack nativi e Java nella tua app. In genere si riferisce al numero di thread in esecuzione nella tua app.

  • Codice: memoria utilizzata dalla tua app per codice e risorse, ad esempio dex bytecode, codice dex ottimizzato o compilato, librerie .so e caratteri.

  • Altri: memoria utilizzata dalla tua app che il sistema non sa come classificare.

  • Allocato: il numero di oggetti Java/Kotlin allocati dalla tua app. Non vengono conteggiati gli oggetti allocati in C o C++.

    In caso di connessione a un dispositivo con Android 7.1 e versioni precedenti, il conteggio dell'allocazione inizia solo nel momento in cui il Memory Profiler si connette all'app in esecuzione. Di conseguenza, gli oggetti allocati prima di iniziare la profilazione non vengono presi in considerazione. Tuttavia, Android 8.0 e versioni successive include uno strumento di profilazione on-device che tiene traccia di tutte le allocazioni, pertanto questo numero rappresenta sempre il numero totale di oggetti Java in sospeso nella tua app su Android 8.0 e versioni successive.

Rispetto al numero di memoria del precedente strumento di monitoraggio di Android, il nuovo Memory Profiler registra la tua memoria in modo diverso, quindi potrebbe sembrare che la tua memoria sia ora più elevata. Il Profiler di memoria monitora alcune categorie aggiuntive che aumentano il totale, ma se ti interessa solo la memoria heap Java, il numero "Java" dovrebbe essere simile al valore dello strumento precedente. Anche se il numero Java probabilmente non corrisponde esattamente a quello che hai visto in Android Monitoring, il nuovo numero tiene conto di tutte le pagine di memoria fisica che sono state allocate all'heap Java della tua app poiché è stato creato con il fork di Zygote. Ciò fornisce una rappresentazione accurata della quantità di memoria fisica effettivamente utilizzata dalla tua app.

Visualizza allocazioni della memoria

Le allocazioni della memoria mostrano come sono stati allocati ogni oggetto Java e riferimento JNI nella memoria. In particolare, il Profiler di memoria può mostrare quanto segue sulle allocazioni degli oggetti:

  • Quali tipi di oggetti sono stati assegnati e quanto spazio utilizzano.
  • L'analisi dello stack di ogni allocazione, incluso il thread.
  • Quando gli oggetti sono stati assegnati alla posizione (solo se si utilizza un dispositivo con Android 8.0 o versioni successive).

Per registrare le allocazioni Java e Kotlin, seleziona Registra allocazioni Java / Kotlin, quindi seleziona Record. Se sul dispositivo è installato Android 8 o versioni successive, l'interfaccia utente di Memory Profiler passa a una schermata separata che mostra la registrazione in corso. Puoi interagire con la sequenza temporale mini sopra la registrazione (ad esempio per modificare l'intervallo di selezione). Per completare la registrazione, seleziona Interrompi .

Visualizzazione delle allocazioni Java in Memory Profiler

Su Android 7.1 e versioni precedenti, il profiler della memoria utilizza la registrazione dell'allocazione legacy, che mostra la registrazione nella sequenza temporale finché non fai clic su Interrompi.

Dopo aver selezionato una regione della sequenza temporale (o quando termini una sessione di registrazione con un dispositivo con Android 7.1 o versioni precedenti), viene visualizzato l'elenco degli oggetti allocati, raggruppati per nome della classe e ordinati in base al numero di heap.

Per esaminare il record di allocazione:

  1. Sfoglia l'elenco per trovare oggetti con un conteggio di heap insolitamente elevato e che potrebbero essere divulgati. Per trovare le classi note, fai clic sull'intestazione della colonna Nome classe per ordinare in ordine alfabetico. Quindi, fai clic sul nome di un corso. A destra viene mostrato il riquadro Visualizzazione istanza, che mostra tutte le istanze di quella classe, come mostrato nella Figura 3.
    • In alternativa, puoi individuare rapidamente gli oggetti facendo clic su Filtra o premendo Ctrl+F (Comando+F su Mac) e inserendo il nome di una classe o di un pacchetto nel campo di ricerca. Puoi anche cercare in base al nome del metodo se selezioni Ordina per callback dal menu a discesa. Se vuoi utilizzare le espressioni regolari, seleziona la casella accanto a Regex. Seleziona la casella accanto a Maiuscole/minuscole se la tua query di ricerca è sensibile alle maiuscole.
  2. Nel riquadro Visualizzazione istanza, fai clic su un'istanza. Di seguito viene visualizzata la scheda Stack di chiamate, che mostra dove è stata allocata l'istanza e in quale thread.
  3. Nella scheda Stack di chiamate, fai clic con il tasto destro del mouse su una riga qualsiasi e scegli Vai all'origine per aprire il codice nell'editor.

Figura 3. I dettagli relativi a ogni oggetto allocato sono riportati nella visualizzazione dell'istanza sulla destra

Puoi utilizzare i due menu sopra l'elenco degli oggetti assegnati per scegliere l'heap da esaminare e come organizzare i dati.

Dal menu a sinistra, scegli l'heap da esaminare:

  • heap predefinito: quando il sistema non specifica alcun heap.
  • image heap: l'immagine di avvio del sistema, contenente classi precaricate durante il tempo di avvio. Le allocazioni qui non verranno mai spostate o non verranno rimosse.
  • heap zigote: l'heap di copia su scrittura da cui viene eseguito il fork di un processo di un'app nel sistema Android.
  • heap di app: l'heap principale su cui l'app assegna la memoria.
  • heap JNI: l'heap che mostra dove vengono allocati e rilasciati i riferimenti Java Native Interface (JNI).

Nel menu a destra, scegli come organizzare le allocazioni:

  • Ordina per classe: raggruppa tutte le allocazioni in base al nome della classe. Questa è l'impostazione predefinita.
  • Ordina per pacchetto: raggruppa tutte le allocazioni in base al nome del pacchetto.
  • Ordina per tack di chiamata: raggruppa tutte le allocazioni nello stack di chiamate corrispondente.

Migliora le prestazioni delle app durante la profilazione

Per migliorare le prestazioni dell'app durante la profilazione, per impostazione predefinita il profiler di memoria campiona periodicamente le allocazioni della memoria. Durante i test su dispositivi con livello API 26 o superiore, puoi modificare questo comportamento utilizzando il menu a discesa Allocation Tracking (Monitoraggio dell'allocazione). Le opzioni disponibili sono le seguenti:

  • Completa: acquisisce tutte le allocazioni degli oggetti in memoria. Questo è il comportamento predefinito in Android Studio 3.2 e versioni precedenti. Se hai un'app che assegna molti oggetti, potresti notare rallentamenti visibili nell'app durante la profilazione.
  • Campionata: le allocazioni degli oggetti campionate in memoria a intervalli regolari. Questa è l'opzione predefinita e ha un impatto minore sulle prestazioni dell'app durante la profilazione. Le app che allocano molti oggetti in un breve periodo di tempo potrebbero comunque mostrare rallentamenti visibili.
  • Off. Interrompe il monitoraggio dell'allocazione della memoria da parte dell'app.

Visualizza i riferimenti a JNI globali

Java Native Interface (JNI) è un framework che consente al codice Java e al codice nativo di effettuare chiamate a vicenda.

I riferimenti JNI sono gestiti manualmente dal codice nativo, quindi è possibile che gli oggetti Java utilizzati dal codice nativo rimangano attivi troppo a lungo. Alcuni oggetti nell'heap Java potrebbero non essere raggiungibili se un riferimento JNI viene ignorato senza prima essere stato eliminato esplicitamente. Inoltre, è possibile esaurire il limite globale di riferimento JNI.

Per risolvere questi problemi, utilizza la visualizzazione heap JNI in Memory Profiler per sfogliare tutti i riferimenti JNI globali e filtrarli per tipi di Java e stack di chiamate native. Con queste informazioni, puoi scoprire quando e dove vengono creati ed eliminati i riferimenti JNI globali.

Mentre l'app è in esecuzione, seleziona una parte della sequenza temporale che vuoi esaminare e seleziona heap JNI dal menu a discesa sopra l'elenco dei corsi. Puoi quindi ispezionare gli oggetti nell'heap come faresti normalmente e fare doppio clic sugli oggetti nella scheda Allocation Call Stack per vedere dove vengono allocati e rilasciati i riferimenti JNI nel codice, come mostrato nella Figura 4.

Figura 4. Visualizzazione dei riferimenti JNI globali

Per controllare le allocazioni della memoria per il codice JNI dell'app, devi eseguire il deployment dell'app su un dispositivo con Android 8.0 o versioni successive.

Per ulteriori informazioni su JNI, consulta i suggerimenti per JNI.

Profiler della memoria nativa

Android Studio Memory Profiler include un Profiler di memoria nativo per le app di cui è stato eseguito il deployment su dispositivi fisici e virtuali con Android 10 e versioni successive.

Il Profiler della memoria nativo traccia le allocazioni/deallocazioni degli oggetti nel codice nativo per un periodo di tempo specifico e fornisce le seguenti informazioni:

  • Allocazioni: un conteggio di oggetti allocati tramite malloc() o l'operatore new durante il periodo di tempo selezionato.
  • Deallocations: un conteggio di oggetti assegnati tramite free() o l'operatore delete durante il periodo di tempo selezionato.
  • Dimensioni allocazioni: le dimensioni aggregate in byte di tutte le allocazioni durante il periodo di tempo selezionato.
  • Dimensioni deallocations: le dimensioni aggregate in byte di tutta la memoria liberata durante il periodo di tempo selezionato.
  • Conteggio totale: il valore della colonna Allocazioni meno il valore della colonna Deallocations.
  • Dimensioni rimanenti: il valore della colonna Dimensioni allocazione meno il valore della colonna Dimensioni deal.

Profiler della memoria nativa

Per registrare le allocazioni native sui dispositivi con Android 10 e versioni successive, seleziona Registra allocazioni native, quindi Registra. La registrazione continua finché non fai clic su Interrompi , dopodiché l'interfaccia utente di Memory Profiler passa a una schermata separata che mostra la registrazione nativa.

Pulsante Registra allocazioni native

Su Android 9 e versioni precedenti, l'opzione Registra allocazioni native non è disponibile.

Per impostazione predefinita, Profiler della memoria nativa utilizza una dimensione del campione di 32 byte: ogni volta che vengono allocati 32 byte di memoria, viene acquisito uno snapshot di memoria. Una dimensione del campione più piccola genera snapshot più frequenti e dati più accurati sull'utilizzo della memoria. Una dimensione maggiore del campione produce dati meno precisi, ma consumerà meno risorse sul tuo sistema e migliorerà le prestazioni durante la registrazione.

Per modificare la dimensione del campione di Profiler della memoria nativa:

  1. Seleziona Esegui > Modifica configurazioni.
  2. Seleziona il modulo dell'app nel riquadro a sinistra.
  3. Fai clic sulla scheda Profilazione e inserisci la dimensione del campione nel campo Intervallo di campionamento della memoria nativa (byte).
  4. Crea ed esegui di nuovo la tua app.

Acquisisci un dump dell'heap

Un dump dell'heap mostra quali oggetti nella tua app utilizzano memoria nel momento in cui acquisisci il dump dell'heap. Soprattutto dopo una sessione utente estesa, un dump dell'heap può aiutare a identificare le perdite di memoria, mostrando gli oggetti ancora in memoria che credi non dovrebbero più essere presenti.

Dopo aver acquisito un dump dell'heap, puoi visualizzare quanto segue:

  • I tipi di oggetti assegnati dalla tua app e quanti di ognuno.
  • La quantità di memoria utilizzata da ciascun oggetto.
  • La posizione dei riferimenti a ciascun oggetto nel codice.
  • Lo stack di chiamate a cui è stato allocato un oggetto. (gli stack di chiamate sono attualmente disponibili con un dump dell'heap solo con Android 7.1 e versioni precedenti quando acquisisci il dump dell'heap durante la registrazione delle allocazioni.)

Per acquisire un dump dell'heap, fai clic su Acquisisci dump dell'heap, quindi seleziona Registra. 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 dell'app e richiede una parte di memoria per raccogliere i dati.

Al termine dell'acquisizione del dump dell'heap da parte del profiler, l'interfaccia utente di Memory Profiler passa a una schermata separata che mostra il dump dell'heap.

Figura 5. Visualizzazione del dump dell'heap.

Se hai bisogno di maggiore precisione in merito alla creazione del dump, puoi creare un dump dell'heap nel punto critico del codice dell'app chiamando dumpHprofData().

Nell'elenco dei corsi, puoi visualizzare le seguenti informazioni:

  • Allocazioni: numero di allocazioni nell'heap.
  • Dimensioni native: quantità totale di memoria nativa utilizzata da questo tipo di oggetto (in byte). Questa colonna è visibile solo per Android 7.0 e versioni successive.

    Vedrai la memoria qui per alcuni oggetti allocati in Java, perché Android utilizza la memoria nativa per alcune classi di framework, ad esempio Bitmap.

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

  • Dimensioni conservate: la dimensione totale della memoria conservata a causa di tutte le istanze di questa classe (in byte).

Puoi utilizzare i due menu sopra l'elenco degli oggetti assegnati per scegliere i dump dell'heap da esaminare e come organizzare i dati.

Dal menu a sinistra, scegli l'heap da esaminare:

  • heap predefinito: quando il sistema non specifica alcun heap.
  • heap di app: l'heap principale su cui l'app assegna la memoria.
  • image heap: l'immagine di avvio del sistema, contenente classi precaricate durante il tempo di avvio. Le allocazioni qui non verranno mai spostate o non verranno rimosse.
  • heap zigote: l'heap di copia su scrittura da cui viene eseguito il fork di un processo di un'app nel sistema Android.

Nel menu a destra, scegli come organizzare le allocazioni:

  • Ordina per classe: raggruppa tutte le allocazioni in base al nome della classe. Questa è l'impostazione predefinita.
  • Ordina per pacchetto: raggruppa tutte le allocazioni in base al nome del pacchetto.
  • Ordina per tack di chiamata: raggruppa tutte le allocazioni nello stack di chiamate corrispondente. Questa opzione funziona solo se acquisisci il dump dell'heap durante la registrazione delle allocazioni. Anche in questo caso, è probabile che nell'heap siano presenti oggetti che sono stati allocati prima di iniziare la registrazione, quindi queste allocazioni vengono visualizzate per prime, semplicemente elencate per nome della classe.

L'elenco viene ordinato in base alla colonna Dimensioni conservate per impostazione predefinita. Per ordinare i dati in base ai valori di una colonna diversa, fai clic sull'intestazione della colonna.

Fai clic sul nome di una classe per aprire la finestra Visualizzazione istanza sulla destra (nella figura 6). Ogni istanza elencata include:

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

Figura 6. La durata necessaria per acquisire un dump heap è indicata nella sequenza temporale

Per ispezionare l'heap:

  1. Sfoglia l'elenco per trovare oggetti con un conteggio di heap insolitamente elevato e che potrebbero essere divulgati. Per trovare le classi note, fai clic sull'intestazione della colonna Nome classe per ordinare in ordine alfabetico. Quindi, fai clic sul nome di un corso. A destra viene mostrato il riquadro Visualizzazione istanza, che mostra ogni istanza di quella classe, come mostrato nella Figura 6.
    • In alternativa, puoi individuare rapidamente gli oggetti facendo clic su Filtra o premendo Ctrl+F (Comando+F su Mac) e inserendo il nome di una classe o di un pacchetto nel campo di ricerca. Puoi anche cercare in base al nome del metodo se selezioni Ordina per callback dal menu a discesa. Se vuoi utilizzare le espressioni regolari, seleziona la casella accanto a Regex. Seleziona la casella accanto a Maiuscole/minuscole se la tua query di ricerca è sensibile alle maiuscole.
  2. Nel riquadro Visualizzazione istanza, fai clic su un'istanza. Sotto viene visualizzata la scheda Riferimenti, che mostra ogni riferimento all'oggetto.

    In alternativa, fai clic sulla freccia accanto al nome dell'istanza per visualizzare tutti i relativi campi, quindi fai clic sul nome di un campo per visualizzarne tutti i riferimenti. Se vuoi visualizzare i dettagli dell'istanza per un campo, fai clic con il tasto destro del mouse sul campo e seleziona Vai all'istanza.

  3. Nella scheda Riferimenti, se identifichi un riferimento che potrebbe perdere memoria, fai clic con il tasto destro del mouse e seleziona Vai all'istanza. Viene selezionata l'istanza corrispondente dal dump dell'heap, mostrando i dati dell'istanza.

Nel dump dell'heap, cerca le perdite di memoria causate da uno dei seguenti problemi:

  • Riferimenti di lunga durata a Activity, Context, View, Drawable e altri oggetti che potrebbero contenere un riferimento al contenitore Activity o Context.
  • Classi interne non statiche, come Runnable, che possono contenere un'istanza Activity.
  • Cache che contengono oggetti più a lungo del necessario.

Salva un dump dell'heap come file HPROF

Dopo aver acquisito un dump dell'heap, i dati sono visualizzabili in Memory Profiler solo mentre il profiler è in esecuzione. Quando esci dalla sessione di profilazione, perdi il dump dell'heap. Quindi, se vuoi salvarlo per la revisione in un secondo momento, esporta il dump dell'heap in un file HPROF. In Android Studio 3.1 e versioni precedenti, il pulsante Esporta acquisizione in file si trova sul lato sinistro della barra degli strumenti sotto la sequenza temporale; in Android Studio 3.2 e versioni successive è presente un pulsante Esporta dump heap a destra di ogni voce Heap Dump nel riquadro Sessioni. Nella finestra di dialogo Esporta come visualizzata, salva il file con l'estensione del nome file .hprof.

Per utilizzare un analizzatore HPROF diverso come jhat, devi convertire il file HPROF dal formato Android al formato Java SE HPROF. Puoi farlo con lo strumento hprof-conv disponibile nella directory android_sdk/platform-tools/. Esegui il comando hprof-conv con due argomenti: il file HPROF originale e il percorso in cui scrivere il file HPROF convertito. Ecco alcuni esempi:

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

Importa un file di dump dell'heap

Per importare un file HPROF (.hprof), fai clic su Avvia una nuova sessione di profilazione nel riquadro Sessioni, seleziona Carica da file e scegli il file dal browser di file.

Puoi anche importare un file HPROF trascinandolo dal browser di file in una finestra dell'editor.

Rilevamento di perdite in Memory Profiler

Quando analizzi un dump dell'heap in Memory Profiler, puoi filtrare i dati di profilazione che Android Studio ritiene possano indicare perdite di memoria per le istanze Activity e Fragment della tua app.

I tipi di dati mostrati dal filtro includono:

  • Activity istanze che sono state eliminate, ma a cui viene ancora fatto riferimento.
  • Fragment istanze che non hanno un valore FragmentManager valido, ma a cui viene ancora fatto riferimento.

In alcune situazioni, come quelle riportate di seguito, il filtro potrebbe generare falsi positivi:

  • Un elemento Fragment è stato creato ma non è stato ancora utilizzato.
  • Un Fragment viene memorizzato nella cache, ma non fa parte di un FragmentTransaction.

Per utilizzare questa funzionalità, devi prima acquisire un dump dell'heap o importare un file di dump dell'heap in Android Studio. Per visualizzare i frammenti e le attività che potrebbero perdere memoria, seleziona la casella di controllo Attività/perdite di frammentazioni nel riquadro heapdump di Memory Profiler, come mostrato nella Figura 7.

Profiler: rilevamento della perdita di memoria

Figura 7. Filtro di un dump dell'heap per le perdite di memoria.

Tecniche per la profilazione della memoria

Durante l'uso di Memory Profiler, dovresti sollecitare 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' di tempo prima di esaminare l'heap. Potrebbero verificarsi perdite fino in cima alle allocazioni nell'heap. Tuttavia, più piccola è la fuga, più tempo sarà necessario per eseguire l'app per vederla.

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

  • Ruota il dispositivo da verticale a orizzontale e poi di nuovo all'indietro più volte in diversi stati di attività. La rotazione del dispositivo spesso può causare la perdita di un oggetto Activity, Context o View, perché il sistema ricrea Activity e se la tua app contiene un riferimento a uno di questi oggetti altrove, il sistema non può eseguire la garbage collection.
  • Passa dalla tua app a un'altra app in diversi stati dell'attività (vai alla schermata Home e torna all'app).

Suggerimento: puoi eseguire i passaggi precedenti anche utilizzando il framework di test monkeyrunner.