Canary Leak — Um “X9 do Bem”

Klaus Dellano
HavanLabs
Published in
3 min readMay 6, 2024

Se você já enfrentou desafios com vazamentos de memória que deixam seus aplicativos lentos ou até mesmo instáveis, você vai gostar de conhecer a Canary Leak.

Mas o que são vazamentos de memória?

São situações em que a memória que deveria ser liberada não é, levando a uma diminuição progressiva da memória disponível. Isso pode causar lentidão e até mesmo fazer com que o aplicativo pare de funcionar.

O que é a Canary Leak?

A Canary Leak é uma ferramenta de detecção (X9) de vazamento de memória. Com ela, é possível identificar e corrigir esse problemas em seus aplicativos Android de forma eficiente, podendo ser uma verdadeira aliada na otimização dos seus apps…

ta… blz… e quais a vantagens?…

Com uma interface intuitiva, uso simples e verificação em tempo real… são os principais pontos que ajudam na identificação dos vazamentos e agilizam o processo de correção.

e como se usa esse treco?

Imagine que você está desenvolvendo um aplicativo e, de repente, ele começa a ficar lento (coisa chata né?). Segue os exemplos mais comuns (e que pode até ser o seu)…

  • Monitoramento de Fragmentos
    Se você estiver trabalhando com múltiplos fragmentos e observar que eles não estão sendo destruídos corretamente. Pode ser que exista algum vazamento de memória associado a eles.
    Por exemplo, você pode ter um fragmento que não está sendo destruído porque está retendo uma referência a uma Activity.
class MyFragment: Fragment() {
private lateinit var myActivity: Activity

override fun onAttach(context: Context) {
super.onAttach(context)
myActivity = context as Activity
}
}
  • Verificação de Listeners
    Listeners são uma fonte comum de vazamentos de memória.
    Por exemplo, você pode registrar um listener, mas esquecer de ‘desregistrar’ quando não for mais necessário.
class MyActivity: Activity() {
private val myListener = MyListener()

override fun onStart() {
super.onStart()
MySingleton.registerListener(myListener)
}

override fun onStop() {
super.onStop()
// Esquecemos de desregistrar o listener aqui
// Obrigado CanaryLeak 'S2'
}
}
  • Examinar o uso de objetos grandes
    Objetos grandes que são mantidos na memória podem causar problemas de desempenho.
    Será que esses objetos estão sendo retidos por mais tempo do que o necessário?
class BigObjectActivity: Activity() {
private lateinit var bigObject: BigObject

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
bigObject = BigObject()
}

// Esquecemos de liberar o bigObject aqui
// CanaryLeak, nos te amamos!
}
  • Verificação de Serviços
    Serviços em Android podem ser uma fonte de vazamentos de memória, especialmente se eles retêm contextos.
class MyService : Service() {
private lateinit var myContext: Context

override fun onCreate() {
super.onCreate()
myContext = this
}
}
  • Análise de Threads
    Threads que não são interrompidas corretamente podem causar vazamentos de memória.
    Suponha que você tenha uma Thread executando em segundo plano para realizar uma tarefa longa, como baixar um arquivo.
class DownloadThread(private val url: String) : Thread() {
override fun run() {
// Código para baixar o arquivo aqui
}
}

Agora, se você iniciar esta Thread em uma Activity…

class MyActivity : Activity() {
private lateinit var downloadThread: DownloadThread

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
downloadThread = DownloadThread("<http://example.com/file>")
downloadThread.start()
}
}

… e então sair da Activity antes da Thread terminar, a Thread poderá reter uma referência da Activity, causando um vazamento de memória.

Este é um exemplo típico de vazamento que pode ser difícil de detectar sem uma ferramenta como o Canary Leak.

Ao usar o Canary Leak, você seria notificado sobre o problema e poderia então tomar medidas para corrigi-lo… poderia, por exemplo, fazer com que a Thread seja interrompida quando a Activity for destruída:

class MyActivity : Activity() {
private lateinit var downloadThread: DownloadThread

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
downloadThread = DownloadThread("<http://example.com/file>")
downloadThread.start()
}

override fun onDestroy() {
super.onDestroy()
if (downloadThread.isAlive) { // Agradeça ao Canary Leak
downloadThread.interrupt()
}
}
}

Desta forma, a Thread não reterá mais a Activity depois que ela for destruída, evitando o vazamento de memória.

Resumindo…

a Canary Leak é uma ferramenta que facilita a identificação e correção de vazamentos de memória, ajudando a melhorar a performance dos seus aplicativos. (Essencial para qualquer desenvolvedor Android)…

Iai? Deu vontade de usar essa ferramenta? Ou você utiliza outras opções para melhorar a performance? Quais?

--

--

Klaus Dellano
HavanLabs

Developer Engineer at HAVAN, focusing on Mobile and RFID.