Capítulo 5 Garbage Collector Introdução Funcionamento do Garbage Collector Execução do Garbage Collector O método finalize() Preparando o objeto para a coleta Obtendo dados sobre memória Configurações de memória Ciclo de vida dos objetos Tipos de referência 2 Introdução Exploraremos aqui alguns aspectos da linguagem de programação Java quanto à utilização da memória do computador. 3 Introdução Durante o seu ciclo de vida, uma aplicação Java consome recursos de memória conforme sua necessidade alocando espaços para reter as informações utilizadas durante o processamento. 4 Introdução c p o s Cliente c = new Cliente(); Produto p = new Produto(); String s = “Impacta”; Object o = p; c = new Cliente(); p = new Produto(); s = null; 5 Introdução Após a execução de instruções, a memória do computador pode reter informações desnecessárias e não mais utilizadas pela aplicação Estas informações são consideradas lixo de memória. c p o s 6 Introdução Em linguagens de programação como C e C++, tais alocações devem ser explicitamente removidas pela aplicação a fim de liberar estes espaços de memória. A não-liberação destes recursos de memória pode acarretar a perda de performance da aplicação e impedir que outras informações mais importantes sejam carregadas, causando falhas como “out of memory”, “stack overflow” e, em alguns casos, reter lixo em memória mesmo após o encerramento da aplicação. 7 Garbage Collector O Garbage Collector é um recurso da linguagem Java responsável pela limpeza automática das informações não mais utilizadas pela aplicação. O Garbage Collector retira do programador Java a responsabilidade de desalocar os recursos de memória utilizados pela aplicação. 8 Execução do Garbage Collector O Garbage Collector é automaticamente executado de tempos em tempos pelo JVM. Todavia, podemos programaticamente solicitar ao JVM a execução do Garbage Collector através da instrução abaixo: System.gc(); Vale observar que o uso da instrução System.gc() não garante que o JVM realize a execução imediata do Garbage Collector, por questões de disponibilidade de processamento. 9 O método finalize() Ao coletar cada um dos objetos considerados lixo de memória, o Garbage Collector executa para cada um deles o método finalize() O finalize() – também chamado de método destrutor – é um método presente na classe Object e, portanto, herdado por toda e qualquer classe presente na linguagem. 10 O método finalize() O método finalize() possui a funcionalidade inversa ao método construtor. É executado pelo GC quando o objeto é elimidado da memória. 11 O método finalize() Ao criar uma classe, podemos sobrescrever o método finalize() adicionando instruções de encerramento e finalização. public class Cliente { ... ... protected void finalize() { ... gravarDados(); enviarEmail(); ... } } 12 Preparando o objeto para coleta Um objeto é considerado um candidato para coleta – ou coletável – quando não possui mais nenhuma referência na aplicação apontando para ele. Existem tipicamente três situações em que o objeto é preparado para coleta tornando-se coletável. Exclusão de referência Alteração de referência Isolamento de referência 13 Preparando o objeto para coleta Exclusão de referência Ocorre quando a variável que aponta para aquele objeto perde o seu escopo ou é anulada c = new Object(); .... .... c = null; c 14 Preparando o objeto para coleta Alteração de referência Ocorre quando a variável que apontava para um objeto passa a apontar para um outro objeto. c = new Object(); .... .... c = new Object(); c 15 Preparando o objeto para coleta Isolamento de referência O Garbage Collector consegue identificar também referências circulares em sua aplicação, removendo-as caso seja necessário x = new Funcionario(); y = new Funcionario(); x.setEncarregado(y); y.setEncarregado(x); y = null; x = null; x y 16 Obtendo dados sobre a memória Durante a execução de uma aplicação, podemos obter informações de memória através da classe java.lang.Runtime Runtime runtime = Runtime.getRuntime(); long free = runtime.freeMemory(); long total = runtime.totalMemory(); long max = runtime.maxMemory(); System.out.printf("Memória livre : %,12d%n", free); System.out.printf("Memória total : %,12d%n", total); System.out.printf("Memória limite: %,12d%n", max); 17 Configurações de memória Ao executar uma aplicação Java, podemos definir a quantidade de memória que o sistema operacional disponibilizará para o JVM: java -Xms128m -Xmx512m OlaMundo 18 Configurações de memória -Xms Define a quantidade inicial de memória a ser utilizada pelo JVM. -Xmx Define a quantidade máxima de memória que o sistema operacional alocará para o JVM. 19 Ciclo de vida dos objetos Created In use Invisible Unreachable Collected Finalized Deallocated 20 Ciclo de vida dos objetos Created In use Unreachable Collected Finalized Invisible Created O ciclo de vida do objeto começa com o estado “Created”, quando o JVM já alocou espaço em memória para registrar todos os membros de dados do objeto, mas ainda não o inicializou. Deallocated 21 Ciclo de vida dos objetos Created In use Unreachable Collected Finalized Deallocated Invisible In use Após a criação, o JVM realiza a inicialização do objeto, executando os passos na seguinte ordem 1. 2. 3. 4. Incializa os membros da classe mãe; Executa o construtor da classe mãe; Inicializa os membros da própria classe; Executa o construtor da própria classe. 22 Ciclo de vida dos objetos Created In use Unreachable Collected Finalized Deallocated Invisible Invisible Ao longo da aplicação, o objeto podese tornar invisível. Isto ocorre quando a(s) sua(s) referência(s) está(ão) fora do escopo atual, onde não podemos manipular aquele objeto diretamente. 23 Ciclo de vida dos objetos Created In use Unreachable Collected Finalized Invisible Unreachable Um objeto torna-se unreachable (inalcançável) quando não há mais nenhuma referência (variável) apontando para ele, tornando-se candidato a ser coletado. Deallocated 24 Ciclo de vida dos objetos Created In use Unreachable Collected Finalized Invisible Collected O objeto coletado é aquele que já foi identificado pelo GC para coleta mas ainda não teve a oportunidade de iniciar o processo de finalização deste. Deallocated 25 Ciclo de vida dos objetos Created In use Unreachable Collected Finalized Invisible Finalized O objeto é considerado finalizado quando o GC já executou o seu método finalize(), mas ainda não desalocou o espaço de memória ocupado por este. Deallocated 26 Ciclo de vida dos objetos Created In use Unreachable Collected Finalized Deallocated Invisible Deallocated Última etapa do ciclo de vida do objeto. Ao ser desalocado, o espaço de memória que antes era ocupado pelo objeto torna-se totalmente liberado como se o objeto nunca tivesse existido. 27 Tipos de referência Existem diferentes tipos de referências à objetos que podem ser utilizados pela aplicação: Referência strong Referência soft Referência weak Referência phantom 28 Tipos de referência Referência strong Referência strong Referência soft Referência weak Referência phantom 29 Tipos de referência Até o momento temos utilizado variáveis comuns para referenciar objetos em memória. Tais variáveis são chamadas “strong”. Uma variável strong é uma variável cujo objeto apontado nunca é coletado pelo GC. 30