Introdução
O gerenciamento de memória é essencial em muitos aplicativos. Como exemplo poderíamos considerar um programa que lê uma quantidade grande de elementos e armazena esses elementos posteriormente num banco de dados. Caso o gerenciamento de memória não seja realizado com sucesso, ou seja, eliminando da memória os elementos que já foram gravados e não precisarão mais serem utilizados, podemos ter um vazamento de memória podendo assim travar o software deixando-o inoperável. Esse tipo de problema acontece com maior freqüência em aplicativos complexos. Esse tipo de falha lógica na liberação de memória pode ocorrer com mais freqüência em linguagens como C e C++ que não possuem coleta automática de lixo ficando tudo a cargo do desenvolvedor controlar o gerenciamento da memória. Esse tipo de coleta de lixo automática é muito discutível, alguns acham melhor outros acham que não vale a pena esse tipo de esforço.
Por isso Java oferece uma opção automática para o gerenciamento de memória. O gerenciamento automático de memória o livrará de qualquer tipo de controle manual sobre objetos que devem ser liberados da memória. A única desvantagem desse gerenciamento automático de memória é que o programador não saberá exatamente quando ele será executado.
O coletor de lixo nada mais faz do que procurar objetos na memória que não possam mais ser alcançados, ou seja, aqueles objetos que não são mais usados no programa são excluídos da memória liberando assim mais espaço.
Funcionamento
O controlador de lixo não é controlado pelo programador e sim pela Máquina Virtual Java que decide quando executá-lo. Em breve veremos que há a possibilidade do programador chamar o coletor de lixo, porém mesmo assim não há nenhuma garantia de que o coletor de lixo irá realmente ser executado naquele momento. Normalmente o coletor executa quando percebe-se que a memória está ficando sem espaço.
Infelizmente a especificação da linguagem Java não garante como é o funcionamento do coletor de lixo, nem mesmo indica algum algoritmo que ele utiliza. O importante a saber é em quais objetos o coletor de lixo realmente age. Isso é muito importante porque assim o programador pode agir de forma a ir colocando alguns objetos disponíveis para o coletor de lixo para posteriormente desalojá-lo da memória liberando espaço para outros objetos. É importante ressaltar que o seu aplicativo pode ficar sem memória sim e isso pode travar toda a aplicação e torná-la inoperável para o usuário, o coletor de lixo irá tentar remover apenas aqueles objetos que não forem usados, no entanto, se você tiver muitos objetos ativos o sistema poderá sim ficar sem memória para operar.
Tornando os Objetos Explicitamente Qualificados para Coleta
- Anulando uma Referência
Um objeto se torna disponível para o coletor de lixo quando não há mais referências a ele que possam ser alcançadas, ou seja, o objeto não possui ninguém apontando para ele, ele está simplesmente flutuando no espaço de memória. Para fazer isso basta apontar para null a variável de referência que estiver apontando para ele.
Exemplo:
Listagem 1: Atribuição de valor a string
//Variável de referência teste aponta para um objeto String
String teste = “Hello”;
No momento acima nota-se que existe uma variável apontando para o objeto em questão, nesse momento tem-se que o objeto não está qualificado para a coleta.
Exemplo:
Listagem 2: Passando valor null para variável string
//Variável de referência teste não mais aponta para o objeto String anterior
Teste = null;
Agora sim o objeto String de valor “Hello” está disponível para a coleta, visto que não há mais apontamentos para este objeto.
- Reatribuindo uma Variável de Referência
Outra maneira de qualificar um objeto para a coleta de lixo é desassociando uma variável de referência de um objeto configurando-a para referenciar outro objeto.
Exemplo:
Listagem 3: Objetos não qualificados para coleta
String teste1 = “Ola”;
String teste2 = “Ate Logo!”;
No momento acima tem-se que nenhum dos objetos criados estão qualificados para a coleta, pois ambos possuem uma variável apontando para os objetos.
Exemplo:
Listagem 4: Associação de um objeto a outro
teste1 = teste2;
Agora o objeto String de valor “Ola” está qualificado para o coletor de lixo, pois não há nenhuma variável apontando para o objeto, ambas as variáveis teste1 e teste2 apontam para o objeto String de valor “Ate Logo!”.
Vale ressaltar que objetos criados nos métodos após a execução completa do método estão todos disponíveis para o coletor de lixo, pois variáveis de escopo local são todas destruídas, exceto aquelas retornadas pelos métodos.
Listagem 5: Método no qual são instanciados objetos
public String getInfo() {
String teste1 = “Ola”;
String teste2 = “Ate Logo!”;
return teste2;
}
Nota-se portanto que o objeto String de valor “Ola” será qualificado para o coletor de lixo após o término da execução do método. No entanto, o objeto “Ate Logo!” não será qualificado, pois ele será retornado pelo método e usado por quem está chamando o método.
- Solicitando o GarbageCollection
Uma outra forma de coleta de lixo é tentar forçar chamar o coletor de lixo. Porém vale ressaltar que a própria especificação do Java diz que mesmo tentando “forçar” a coleta de lixo nada garante que ele realmente vá coletar lixo naquele momento, assim não confie tanto nisso, ou seja, a máquina virtual irá tentar acatar a sua solicitação mas nada garante que ela vá satisfazer a sua solicitação naquele exato momento.
Para solicitar a coleta de lixo basta realizar a chamada abaixo:
Listagem 6: Executando a coleta de lixo manualmente
System.gc();
Conclusões
Nesse artigo conseguimos dar um resumo geral sobre o Garbage Collector do Java, este assunto é interessante, importante e bastante abrangente. Mais artigos sobre este assunto serão disponibilizados, visto que há bastante coisa ainda que podemos aprender sobre essa importante funcionalidade que a VM nos disponibiliza. Para um inicio de conversa ficamos por aqui e um até breve aos nossos leitores.