Gerar um heap dump

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 visualização de heap dump no criador de perfil do Android Studio.

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.
As visualizações Instances, Fields e References na janela de ferramentas Heap Dump.

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:

  1. Abra a guia "Profiler" no Android Studio.
  2. Clique em Heap Dump (ou Analyze Memory Usage) e em "Record" para fazer um snapshot do estado atual da memória do app.
  3. 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.
  4. Clique em qualquer entrada sinalizada para abrir o painel Bitmap Preview , que permite ver exatamente qual imagem é a infratora reincidente.
  5. 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.
Procure bitmaps duplicados usando o triângulo de aviso amarelo ⚠️.

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 Activity ou Context que podem vazar o gráfico de composição do Compose hospedado (como ComposeView e os subcomponíveis).
  • Vazamento de objetos de estado do Jetpack Compose (MutableState), titulares de estado ou lambdas que capturam Context.
  • Esquecer de limpar listeners ou observadores no bloco onDispose de um DisposableEffect.
  • Classes internas não estáticas, como a Runnable, que podem conter uma instância de Activity.
  • 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 à Activity ou Context em 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

Outros recursos