Gere um heap dump para ver quais objetos do app estão usando memória no momento da captura e identificar vazamentos de memória ou comportamento de alocação de memória que leva a travamentos, congelamentos e até mesmo falhas do app. É especialmente útil gerar heap dumps após uma sessão de usuário prolongada, quando ele pode mostrar objetos que ainda estão na memória e que já deveriam ter sido removidos dela.
Esta página descreve as ferramentas que o Android Studio oferece para coletar e analisar heap dumps. Como alternativa, é possível inspecionar a memória do app na
linha de comando com dumpsys bem como
ver eventos de coleta de lixo (GC) no Logcat.
Por que é necessário criar o perfil da memória do app
O Android oferece um ambiente de memória gerenciada: quando determina que o app deixou de usar alguns objetos, o coletor de lixo libera a memória não utilizada para a heap. A maneira como o Android encontra memória não utilizada está em constante melhoria, mas, em algum momento, em todas as versões do Android, o sistema precisa pausar brevemente o código. Na maioria das vezes, as pausas são imperceptíveis. No entanto, se o app alocar memória com mais rapidez do que o sistema consegue coletá-la, o app poderá ficar mais lento enquanto o coletor libera memória suficiente para atender às alocações. Esse atraso pode fazer com que o app pule frames e gere uma lentidão visível.
Ainda que não exiba essa lentidão, se o app vazar memória, pode reter essa memória mesmo quando estiver em segundo plano. Esse comportamento pode diminuir o resto da performance de memória do sistema ao forçar eventos desnecessários de coleta de lixo. Com o tempo, o sistema será forçado a encerrar o processo do aplicativo para recuperar a memória. Se isso ocorrer, quando o usuário retornar ao aplicativo, o processo do app precisará ser reiniciado completamente.
Para saber mais sobre práticas de programação que podem reduzir o uso de memória do app, leia Gerenciar a memória do app.
Visão geral do heap dump
Para gerar um heap dump, selecione a tarefa Analyze Memory Usage (Heap Dump) (use Profiler: run 'app' as debuggable (complete data)) para gerar um heap dump. Durante o despejo de heap, a quantidade de memória do Java pode aumentar temporariamente. Isso é normal porque o heap dump ocorre no mesmo processo do app e precisa de memória para coletar os dados. Depois de gerar o heap dump, você verá o seguinte:
A lista de classes mostra as seguintes informações:
- Alocações: número de alocações na heap.
Tamanho Nativo: quantidade total de memória nativa usada por esse tipo de objeto (em bytes). Você verá memória aqui para alguns objetos alocados em Java porque o Android usa memória nativa para algumas classes de estrutura, como
Bitmap.Shallow Size: quantidade total de memória Java usada por esse tipo de objeto (em bytes).
Tamanho Retido: tamanho total da memória que está sendo retida devido a todas as instâncias de essa classe (em bytes).
Use o menu de heap para filtrar para determinadas heaps:
- App heap (padrão): a heap principal na qual o app aloca memória.
- Image heap: a imagem de inicialização do sistema, que contém as classes pré-carregadas durante a inicialização. As alocações aqui nunca são movidas ou eliminadas.
- Zygote heap: a heap copy-on-write em que um processo do app é ramificado de o sistema Android.
Use o menu suspenso de organização para escolher como organizar as alocações:
- Arrange by class (padrão): agrupa as alocações de acordo com o nome da classe.
- Arrange by package: agrupa as alocações com base no nome do pacote.
Use o menu suspenso de classe para filtrar grupos de classes:
- Todas as classes (padrão): mostra todas as classes, incluindo aquelas de bibliotecas e dependências.
- Show activity/fragment leaks: mostra as classes que estão causando vazamentos de memória.
- Show project classes: mostra apenas as classes definidas pelo projeto.
Clique em um nome de classe para abrir o painel Instance. Cada instância listada inclui o seguinte:
- Profundidade: o menor número de saltos de qualquer raiz de GC até a instância selecionada.
- Native Size: o tamanho da instância na memória nativa. Essa coluna fica visível apenas para o Android 7.0 e versões mais recentes.
- Shallow Size: o tamanho da instância na memória Java.
- Tamanho retido: o tamanho da memória dominada por essa instância (de acordo com a árvore dominante).
Clique em uma instância para mostrar os Instance Details, incluindo os Fields
e os References. Os tipos de campo e referência comuns são tipos estruturados
,
matrizes
,
e tipos de dados primitivos
em Java. Clique com o botão direito do mouse em um campo ou referência para acessar a instância ou linha associada no código-fonte.
- Campos: mostra todos os campos nessa instância.
- Referências: mostra todas as referências ao objeto destacado na guia Instance.
Detectar bitmaps duplicados
Também é possível detectar bitmaps redundantes na visualização de heap dump a partir do Android Studio Narwhal 4.
Veja como encontrá-los:
- Abra a guia "Profiler" no Android Studio.
- Clique em Heap Dump (ou Analyze Memory Usage) e em "Record" para fazer um snapshot do estado atual da memória do app.
- Analise os resultados da análise em busca do triângulo de aviso amarelo ⚠️, que o Android Studio usa para sinalizar bitmaps duplicados armazenados várias vezes.
- Como alternativa, navegue até o cabeçalho do criador de perfil, escolha Filter by: e selecione a configuração Duplicate Bitmaps.
- Clique em qualquer entrada sinalizada para abrir o painel Bitmap Preview , que permite ver exatamente qual imagem é a infratora reincidente.
- Use essa confirmação visual para rastrear a lógica de carregamento redundante no código e implementar uma estratégia de armazenamento em cache melhor.
Encontrar vazamentos de memória
Para filtrar rapidamente as classes que podem estar associadas a vazamentos de memória, abra o menu suspenso de classe e selecione Show activity/fragment leaks. O Android Studio
mostra as classes que considera indicar vazamentos de memória para
Activity e
Fragment instâncias no seu app.
Para procurar vazamentos de memória de forma mais manual, navegue pelas listas de classes e instâncias para encontrar objetos com um Retained Size grande. Procure vazamentos de memória causados por:
- Referências de longa duração a
ActivityouContextque podem vazar o gráfico de composição do Compose hospedado (comoComposeViewe os subcomponíveis). - Vazamento de objetos de estado do Jetpack Compose (
MutableState), titulares de estado ou lambdas que capturamContext. - Esquecer de limpar listeners ou observadores no bloco
onDisposede umDisposableEffect. - Classes internas não estáticas, como a
Runnable, que podem conter uma instância deActivity. - Caches que armazenar objetos por mais tempo do que o necessário.
Quando encontrar possíveis vazamentos de memória, use as guias Fields e References em Instance Details para acessar a instância ou a linha de código-fonte de interesse.
Acionar vazamentos de memória para testes
Para analisar o uso da memória, você precisa estressar o código do app e tentar forçar vazamentos de memória. Uma forma de provocar vazamentos de memória no app é deixar que ele seja executado por algum tempo antes de inspecionar a heap. Os vazamentos podem subir para a parte superior das alocações na heap. No entanto, quanto menor o vazamento, mais tempo você precisará executar o app para vê-lo.
Também é possível usar um dos seguintes métodos para provocar um vazamento de memória:
- Gire o dispositivo da orientação retrato para paisagem e vice-versa várias vezes em diferentes estados de atividade. A rotação do dispositivo pode causar um vazamento de
Activity(e, consequentemente, a árvore de interface do Compose hospedada e as árvores de estado associadas) se o app mantiver uma referência àActivityouContextem operações assíncronas ou titulares de estado. - Alterne entre seu app e outro app em diferentes estados de atividade. Por exemplo, navegue até a tela inicial e retorne ao app.
Exportar e importar uma gravação de heap dump
É possível
exportar e importar um arquivo de heap dump
na guia Past Recordings do criador de perfil. O Android Studio salva a gravação como um arquivo .hprof.
Como alternativa, para usar um analisador de arquivos .hprof diferente, como
jhat,
é preciso converter o arquivo .hprof do formato Android para o formato de arquivo .hprof do Java SE. Para converter o formato do arquivo, use a ferramenta hprof-conv fornecida no diretório {android_sdk}/platform-tools/. Execute o comando hprof-conv com dois argumentos: o nome do arquivo .hprof original e o local para gravar o arquivo .hprof convertido, incluindo o novo nome do arquivo .hprof. Exemplo:
hprof-conv heap-original.hprof heap-converted.hprof