Vazamentos de memória e inchaço — o que é, causas e como evitar

Autor: IT Sectr Publicado: 2026-07-28 Tempo de leitura: 10 min

Vazamento de memória — um dos problemas mais insidiosos no desenvolvimento móvel. O uso de memória do aplicativo cresce continuamente até atingir o limite definido pelo SO, seguido por um OutOfMemoryError ou encerramento forçado. De acordo com a Square Engineering, cerca de 40% dos aplicativos Android têm pelo menos um vazamento de memória que só pode ser detectado por meio de perfilamento. Vamos examinar as causas e os métodos para prevenir o crescimento da memória.

Pontos Principais

  • GC reachability — um objeto não é removido se houver uma referência ativa do conjunto raiz
  • Referências estáticas a Activity ou Context — a causa mais comum de vazamentos no Android
  • LeakCanary — a ferramenta padrão para detecção automática de vazamentos no Android
  • WeakReference — uma solução para referências que não devem impedir a coleta de lixo
  • Componentes Lifecycle-aware cancelam automaticamente as assinaturas quando a view é destruída

O que é um vazamento de memória e inchaço do aplicativo?

Vazamento de memória — uma situação em que um objeto que não é mais necessário ao aplicativo continua sendo mantido no heap porque uma referência ativa do conjunto raiz (GC Root) ainda aponta para ele. O coletor de lixo considera esse objeto vivo e não o remove.

Inchaço de memória — um problema mais amplo em que o aplicativo consome mais memória do que o necessário para realizar suas tarefas atuais. Causas: cache excessivo, duplicação de objetos, estruturas de dados subótimas e fragmentação do heap.

No Android, cada aplicativo recebe um heap limitado (geralmente 64–512 MB, dependendo do dispositivo e da versão do SO). No iOS, o limite é menos rigoroso, mas o sistema envia um aviso de memória ao se aproximar do limite.

CaracterísticaAndroidiOS
Limite do heap64–512 MB (depende do dispositivo)Implícito (sistema)
Coleta de lixoART (Concorrente, Compacto)ARC (Contagem Automática de Referências)
Mecanismo de vazamentoReferências GC RootRetain cycles (ciclos de referência forte)
ResultadoOutOfMemoryErrorAviso de memória → encerramento

De acordo com o Facebook Engineering Blog, vazamentos de memória causam ~15% dos relatos de crash em aplicativos móveis. No Android, isso é agravado por ANRs devido a pausas frequentes do GC quando a memória está baixa.

Padrões comuns de vazamento de memória no Android e iOS

Referência estática a Activity — um vazamento clássico do Android. Se um campo estático ou singleton mantém uma referência a uma Activity, ela não será coletada pelo GC mesmo após finish() enquanto o singleton estiver vivo. Uma Activity é um objeto pesado que contém uma hierarquia de views, recursos e Context.

kotlin
object LeakHolder {
    var activityRef: Activity ?= null // leak: static reference to Activity
}

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle ?= null) {
        super.onCreate(savedInstanceState)
        LeakHolder.activityRef = this // ❌ MainActivity will never be GC'd
    }
}

Classes anônimas e lambdas — retêm implicitamente uma referência à classe externa. Se um Runnable ou Callback é passado para um serviço externo e a Activity é destruída, o objeto da classe anônima ainda está na fila e impede que a Activity seja coletada como lixo.

  • Handler com atraso — se a Activity for destruída mas Handler.postDelayed ainda não foi executado, a Activity vaza
  • Thread e AsyncTask — ao girar a tela, a Activity é recriada enquanto a Thread antiga continua segurando uma referência à Activity antiga
  • Retrofit/Callback — um Callback anônimo mantém uma referência ao presenter ou fragment
  • Observadores — assinaturas LiveData ou RxJava sem cancelamento no onDestroy

No iOS, o principal problema são os retain cycles: dois objetos mantêm referências fortes entre si e o ARC não pode zerar a contagem de referências de nenhum deles. Um caso típico: um closure que captura self fortemente e self que mantém uma referência ao closure.

Como detectar vazamentos de memória?

LeakCanary — uma biblioteca da Square para detecção automática de vazamentos no Android. Após a destruição de uma Activity ou Fragment, ela verifica se o objeto foi coletado pelo GC. Se não, faz um heap dump e mostra o trace do vazamento.

kotlin
// LeakCanary 2.x — auto-integration via Application
class ExampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        // LeakCanary auto-installs in debug build
        // via ContentProvider — zero code setup
    }
}

// Force check invocation
AppWatcher.objectWatcher.watch(watchedObject, "leak description")

Android Studio Profiler — uma ferramenta integrada para monitoramento de memória em tempo real. Permite gravar um heap dump, encontrar objetos suspeitos (Retained Size > 1 MB) e rastrear o caminho GC root até cada objeto.

Para iOS, use o Xcode Memory Graph Debugger. Ele visualiza o grafo de objetos na memória, mostra retain cycles e permite detectar instantaneamente referências circulares. Instruments > Allocations também está disponível para monitoramento de longo prazo.

Estratégias de prevenção

WeakReference — um mecanismo básico para referências que não devem interferir na coleta de lixo. Se o GC decidir coletar um objeto, WeakReference retorna null. É usado para callbacks, listeners e referências a componentes de UI de threads em segundo plano.

Componentes Lifecycle-aware — uma abordagem arquitetural implementada no Android Jetpack (Lifecycle, LiveData, Flow, coroutines). As assinaturas são canceladas automaticamente no onDestroy, eliminando a principal classe de vazamentos.

kotlin
class MyViewModel : ViewModel() {
    private val _data = MutableLiveData<List<User>>()
    val data: LiveData<List<User>> get() = _data

    fun loadData() {
        viewModelScope.launch {
            val result = repository.fetchData()
            _data.postValue(result)
            // coroutine auto-cancels on onCleared()
        }
    }
}

viewModelScope e lifecycleScope — CoroutineScope integrados no Android que são cancelados no evento de ciclo de vida correspondente. Isso elimina vazamentos por meio de corrotinas — o cenário mais comum no desenvolvimento Android moderno.

  • Não use referências estáticas a Context, Activity, View ou Fragment
  • Cancele todas as assinaturas RxJava no disposeBag / CompositeDisposable no onDestroy
  • Use [weak self] / [unowned self] em closures do iOS para prevenir retain cycles
  • Verifique Bitmap e objetos grandes — eles devem ser reciclados ou anulados

Ferramentas de perfilamento de memória

Memory Profiler no Android Studio — a ferramenta principal para monitoramento do heap. Mostra alocações ao vivo, instantâneos do heap e contagens de objetos por tipo. Permite gravar um dump e analisá-lo no MAT (Memory Analyzer Tool) para encontrar objetos suspeitos.

Eclipse MAT — um analisador de heap dump de desktop. Após carregar um arquivo HPROF do Android Studio, o MAT constrói uma árvore dominadora, mostra o retain size de cada objeto e oferece análise automática de vazamentos suspeitos através do Leak Suspects Report.

Xcode Memory Graph — um depurador visual de retain cycles. Ao clicar no botão Memory Graph Debugger, o Xcode para o aplicativo, constrói um grafo completo de objetos na memória e destaca retain cycles em vermelho.

FerramentaPlataformaCaracterística
LeakCanaryAndroidDetecção automática de vazamentos após destroy
Memory ProfilerAndroid StudioHeap dump + alocações ao vivo
Eclipse MATAndroidÁrvore dominadora, Leak Suspects Report
Memory GraphiOS (Xcode)Visualizador de retain cycles

De acordo com o Google I/O 2023, aplicativos que usam LeakCanary em builds de depuração reduzem crashes relacionados à memória em 30–50% nos primeiros 2 meses após a adoção. Recomenda-se adicionar o LeakCanary durante a fase de integração do projeto.

Perguntas Frequentes

Qual a diferença entre vazamento de memória e inchaço?

Vazamento — objetos inacessíveis pelo código mas não coletados pelo GC devido a referências ativas. Inchaço — o aplicativo mantém objetos logicamente necessários mas em quantidade excessiva (por exemplo, um cache de 50 MB em um aplicativo em execução de 80 MB). O inchaço é resolvido arquiteturalmente; o vazamento, através do gerenciamento correto de referências.

Como o LeakCanary encontra vazamentos?

LeakCanary usa ObjectWatcher — após onDestroy() de uma Activity, ele cria uma WeakReference para a Activity e executa o GC. Se a WeakReference não for limpa após 5 segundos, o LeakCanary faz um heap dump, analisa a cadeia de referência mais curta do GC Root ao objeto e mostra o stack exato do vazamento com o arquivo e linha de código.

Por que o Bitmap frequentemente causa OutOfMemoryError?

Bitmap ocupa memória fora do heap Java na memória nativa (native heap). O tamanho de um Bitmap = largura × altura × 4 bytes (ARGB_8888). Uma foto de 12 MP (4000×3000) ocupa 48 MB. O Android nem sempre consegue liberar a memória nativa a tempo, então o acúmulo de vários Bitmaps leva a OOM mesmo com heap Java suficiente.

O que é um retain cycle no iOS?

Retain cycle — uma situação no ARC onde dois objetos mantêm referências fortes entre si e a contagem de referências nunca chega a zero. Um exemplo típico: um ViewController com uma referência forte a um closure, e o closure captura self fortemente. Solução: use [weak self] ou [unowned self] nos closures.

Qual é o tamanho máximo do heap no Android?

O tamanho do heap depende do dispositivo e da versão do Android. Para dispositivos antigos (API 15–24) — 64–128 MB. Para os modernos (API 25+) — 256–512 MB. O valor exato pode ser obtido através de ActivityManager.getMemoryClass(). Para aplicativos grandes (jogos, editores), largeHeap=true no manifesto fornece até 1 GB.

Resumo

  • Vazamento de memória — um objeto não coletado pelo GC devido a uma referência ativa do conjunto raiz; inchaço — consumo excessivo de memória sem vazamentos explícitos
  • Referências estáticas a Activity, Context ou View — a causa número um de vazamentos no Android; solução — WeakReference ou Application Context
  • Classes anônimas e lambdas retêm implicitamente uma referência à classe externa; callbacks não cancelados são a segunda causa mais comum
  • LeakCanary — o padrão para detecção automática de vazamentos no Android; a integração leva 5 minutos e reduz a taxa de crashes em 30–50%
  • lifecycleScope e viewModelScope cancelam automaticamente as corrotinas na destruição, eliminando toda uma classe de vazamentos
  • Retain cycles no iOS são resolvidos com weak/unowned self em closures e delegados
  • Perfile a memória pelo menos uma vez por sprint — um heap dump com MAT ou Memory Graph deve se tornar parte do code review

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também