sábado, 15 de dezembro de 2012

Finalização de classes

Este é o processo inverso a construção que é feito pelo método construtor da classe.  Em Java não vemos falar muito disto, como vemos por exemplo em C. A máquina virtual Java provê um mecanismo denominado garbage collector (coletor de lixo) cuja função é liberar a memória quando um objeto não é mais utilizado. Assim em Java não nos preocupamos em liberar memória, este processo é feito "por baixo dos panos" para nós.

O processo de garbage collector é um processo de baixa prioridade que roda em background (thread de baixa prioridade), então ele realiza suas atividades quando não existe muita coisa acontecendo no seu programa, o que para a maioria dos programas é verdade muitas vezes, pois o programa fica esperando durante muito tempo um comando do usuário.

Você poderia pensar então que pode acontecer horas que rodar somente quando o programa está quase inativo é uma forma ruim, pois se estivermos realizando cálculos intensos com grande movimentação de memória poderíamos ter uma situação de precisar de mais memória e esta ainda não ter sido liberada pelo garbage collector. Você está certo e o pessoal do Java pensou nisto também. Quando a memória vai ficando muito baixa, a thread que roda o garbage collector recebe alta prioridade para permitir a liberação de memória que pode ser essencial para podermos rodar nossos programas.

Se olharmos estrutura do objeto Object vemos que ele possui um método finalize

protected void finalize()
                 throws Throwable

Este método provê a finalização do objeto. Neste caso o garbage collector automaticamente libera a memória usada pelo objeto em questão. Normalmente sobrepomos este método (criando o nosso próprio) para liberar algumas coisas que o garbage collector pode ficar sem saber que tem que liberar como por exemplo handler de arquivos abertos ou de conexões de rede.

Diferente do construtor, somente podemos ter um finalize() por classe e o formato dele é o apresentado acima. Note que ele pode gerar algum tipo de exceção.

Vamos pegar emprestado uma classe que já fizemos antes:


Note que chamamos o método da superclasse.

Existem 4 pontos importantes que tenho que apresentar para vocês:
  1. se um objeto tem um finalize(), este método é chamado logo antes do objeto não mais poder ser utilizado, mas logo antes do garbage collector liberar a memória que ele utiliza.
  2. o Java não dá qualquer garantia sobre quando e em que ordem ocorrerá a limpeza pelo garbage collector. Isto significa que se você precisa liberar recursos em uma determinada ordem, você deve fazer isto explicitamente no seu código e não deixar isto para o garbage collector.
  3. o interpretador Java pode sair sem realizar a limpeza completa, desta forma alguns finalize() nem mesmo serão chamados. Se você quiser garantir isto, deve chamar o método Runtime.addShutdownHook. Isto permite que seu código de finalização seja rodado antes do interpretador fechar.
  4. o objeto não é imediatamente liberado da memória ao chamarmos finalize().

Nenhum comentário:

Postar um comentário