# Memory Leak Diagnóstico: Guia Prático em Produção

> Memory Leak Diagnóstico em produção exige processo estruturado para identificar causa raiz antes da queda do sistema. O guia prático apresenta etapas objetivas: monitoramento contínuo de heap, análise de garbage collection, captura de heap dump em picos de uso e comparação de objetos retidos. A metodologia permite distinguir vazamentos reais de crescimento normal de memória, priorizando ações corretivas eficazes.

*PosUp · Apps e Software · 09 de setembro de 2026 · Patrícia Lemos*

Diagnosticar memory leak em produção não precisa ser um bicho de sete cabeças. Com o processo certo, você identifica a causa raiz e resolve antes que o sistema caia. Veja o passo a passo.

Um memory leak em produção é daqueles problemas que não aparecem no teste local, mas que, com o tempo, derrubam o serviço. O sintoma clássico é claro: o uso de memória sobe, sobe, e não desce. O diagnóstico, porém, exige método. Neste guia, você vai aprender a diagnosticar memory leak em produção passo a passo, sem chutar e sem derrubar a aplicação antes de entender o que está acontecendo. Vamos direto ao processo que usamos quando o monitoramento acusa o problema.

## Passo 1: Confirme que é um leak, não um pico

Antes de abrir o heap dump, olhe o gráfico de memória. Um leak tem uma assinatura: a memória cresce de forma contínua e não retorna ao patamar anterior após um pico de uso. Um pico normal sobe e desce. O leak sobe, estabiliza por um tempo, e volta a subir. Acompanhe por algumas horas ou dias, dependendo do tráfego. Se o padrão for de escada, subindo sempre, é leak.

**Erro comum a evitar**: reiniciar a aplicação logo ao ver a memória alta. Isso zera o histórico e esconde o padrão. Deixe o monitoramento registrar pelo menos um ciclo completo de crescimento antes de agir. Se o ambiente for crítico, claro, reinicie para aliviar, mas capture o que der antes.

## Passo 2: Gere um heap dump no momento certo

O heap dump é uma fotografia da memória em um instante. Para diagnosticar um leak, você precisa de pelo menos dois dumps: um quando a memória está em um patamar baixo (logo após um GC, por exemplo) e outro quando está alta, perto do limite. A diferença entre eles mostra o que está sendo retido.

Ferramentas como jmap (para JVM), dotnet-dump (para .NET) ou o comando equivalente no seu runtime geram o dump sem parar a aplicação. No caso da JVM, algo como jmap -dump:live,format=b,file=heap.hprof resolve. O importante é o timing: capture o segundo dump quando o uso de memória estiver no pico.

**Dica prática**: se o ambiente permitir, force um System.gc() antes de tirar o dump "baixo". Isso remove objetos elegíveis e deixa o dump mais limpo para comparação.

## Passo 3: Analise o heap dump com a ferramenta certa

Com os dois dumps em mãos, abra-os em uma ferramenta de análise. O Eclipse MAT é o padrão para JVM, mas o VisualVM também cumpre o papel. Para .NET, o Visual Studio ou a CLI de diagnóstico da Microsoft servem. O objetivo é usar a funcionalidade de comparar dumps (Histogram Diff no MAT) e listar as classes que mais cresceram em número de instâncias.

O que você procura: classes com crescimento acentuado de instâncias entre o primeiro e o segundo dump. Um crescimento de 10% em uma classe que deveria ser descartada é um forte indício. O MAT ainda mostra os caminhos de referência (Path to GC Roots) para cada objeto. É ali que você descobre quem segura a referência: uma lista estática, um cache sem expiração, um listener que nunca foi removido.

**Erro comum**: analisar só o maior objeto do dump. O maior pode ser um buffer legítimo. O leak costuma estar em objetos pequenos que se acumulam. Olhe o crescimento relativo, não o tamanho absoluto.

## Passo 4: Identifique a causa raiz na pilha de referências

Aqui a análise sai do heap e vai para o código. Ao seguir o Path to GC Roots de um objeto retido, você encontra a classe da aplicação que o referencia. Por exemplo, se um UserSession fica preso em um ConcurrentHashMap estático e nunca é removido, o caminho de referência vai mostrar exatamente isso.

Com a classe identificada, revise o código: o objeto foi adicionado a uma coleção e nunca removido? Há um cache com chave que nunca expira? Um recurso externo, como uma conexão ou um stream, foi aberto e não fechado? O leak em produção quase sempre tem uma dessas três origens.

**Dica**: anote o stack trace completo. Ele serve como evidência para a equipe de desenvolvimento e evita que o diagnóstico precise ser refeito.

## Passo 5: Corrija e valide com monitoramento contínuo

A correção depende da causa: remover o objeto da coleção quando não for mais necessário, usar referências fracas (WeakReference) para caches ou garantir que recursos sejam fechados em bloco finally. Após aplicar a correção, não declare vitória no mesmo dia. Acompanhe o gráfico de memória por pelo menos uma semana, em horários de pico, para confirmar que o padrão de escada desapareceu.

**Ressalva**: um único ciclo de GC não é validação. O leak pode ter sido mascarado por um pico de tráfego. O padrão precisa se manter estável ao longo do tempo.

## Checklist final do diagnóstico

Você diagnosticou um memory leak em produção quando:

- Confirmou o padrão de crescimento contínuo no monitoramento.
- Gerou dois heap dumps em momentos distintos.
- Comparou os dumps e encontrou classes com crescimento de instâncias.
- Seguiu o Path to GC Roots e identificou a referência retentora.
- Corrigiu o código e validou com monitoramento prolongado.

Se algum item ficou de fora, o diagnóstico está incompleto. Não pule a etapa de validação prolongada: é ela que separa uma correção real de uma coincidência.

## FAQ: Perguntas frequentes sobre memory leak diagnóstico

### Como sei se minha aplicação tem memory leak ou só uso alto de memória?

Observe o gráfico de uso de memória após um garbage collection. Se a memória retorna a um patamar baixo após o GC, é uso alto, não leak. Se ela continua subindo mesmo após o GC, e o patamar mínimo cresce com o tempo, o leak está presente. Acompanhe por algumas horas para confirmar o padrão.

### Qual a melhor ferramenta para diagnosticar memory leak?

Depende do runtime. Para Java, o Eclipse MAT é o mais usado, com o recurso de comparar dumps. Para .NET, as ferramentas da CLI de diagnóstico da Microsoft ou o Visual Studio funcionam bem. O essencial é que a ferramenta ofereça comparação entre dumps e análise de referências.

### Posso diagnosticar memory leak sem derrubar a aplicação?

Sim. Heap dumps podem ser gerados a quente, sem parar o processo, na maioria dos runtimes modernos. O comando jmap ou dotnet-dump captura o estado da memória sem interromper o serviço. O impacto é um pequeno pause, mas não exige reinício.

### Quantos heap dumps preciso gerar para confirmar o leak?

No mínimo dois: um com a memória em patamar baixo e outro no pico. A comparação entre eles mostra o que está sendo retido. Para diagnósticos mais precisos, três dumps em momentos diferentes ajudam a descartar flutuações normais de tráfego.

### O que fazer se o leak só aparece após vários dias de produção?

Nesse caso, o monitoramento contínuo é seu aliado. Configure alertas para o uso de memória e agende a captura automática de heap dumps quando o limite for atingido. Assim, você tem o dump do momento crítico sem precisar ficar de plantão olhando o gráfico.

### Memory leak tem relação com garbage collection?

Sim, diretamente. Um objeto com referência ativa não é coletado pelo GC, mesmo que não seja mais usado. O leak é justamente isso: referências que impedem a coleta. Entender como o GC do seu runtime decide o que coletar ajuda a prever onde o leak pode se esconder.

---

Fonte (canonical): https://posup.com.br/apps-e-software/memory-leak-diagnostico-guia-pratico-em-producao/
