ISTO DEVE SER OBSOLETO COM JAVA 9!
Use em seu java.util.Cleaner
lugar! (Ou sun.misc.Cleaner
em JRE mais antigo)
Postagem original:
Descobri que o uso de PhantomReferences tem quase a mesma quantidade de armadilhas que os métodos finalizadores (mas menos problemas depois que você acertar). Eu escrevi uma pequena solução (uma estrutura muito pequena para usar PhantomReferences) para Java 8. Ela permite usar expressões lambda como retornos de chamada a serem executados após a remoção do objeto. Você pode registrar os retornos de chamada para recursos internos que devem ser fechados. Com isso eu encontrei uma solução que funciona para mim, pois a torna muito mais prática.
https://github.com/claudemartin/java-cleanup
Aqui está um pequeno exemplo para mostrar como um retorno de chamada é registrado:
class Foo implements Cleanup {
//...
public Foo() {
//...
this.registerCleanup((value) -> {
try {
// 'value' is 'this.resource'
value.close();
} catch (Exception e) {
logger.warning("closing resource failed", e);
}
}, this.resource);
}
E há o método ainda mais simples de fechamento automático, que faz quase o mesmo que o anterior:
this.registerAutoClose(this.resource);
Para responder às suas perguntas:
[então qual é a utilidade disso]
Você não pode limpar algo que não existe. Mas poderia ter recursos que ainda existem e precisam ser limpos para que possam ser removidos.
Mas qual é a utilidade desse conceito / classe?
Não é necessariamente para fazer nada com nenhum efeito diferente de depuração / registro. Ou talvez para estatísticas. Eu vejo isso mais como um serviço de notificação do GC. Você também pode querer usá-lo para remover dados agregados que se tornam irrelevantes depois que o objeto é removido (mas provavelmente existem soluções melhores para isso). Os exemplos geralmente mencionam conexões de banco de dados a serem fechadas, mas não vejo como isso é uma boa ideia, já que você não poderia trabalhar com transações. Uma estrutura de aplicativo fornecerá uma solução muito melhor para isso.
Você já usou isso em algum projeto seu, ou tem algum exemplo onde devemos usar isso? Ou este conceito é feito apenas para o ponto de vista da entrevista;)
Eu o uso principalmente apenas para registro. Assim, posso rastrear os elementos removidos e ver como o GC funciona e pode ser ajustado. Eu não executaria nenhum código crítico dessa maneira. Se algo precisa ser fechado, isso deve ser feito em uma instrução try-with-resource. E eu o uso em testes de unidade, para ter certeza de que não há nenhum vazamento de memória. Da mesma forma que jontejj o faz. Mas minha solução é um pouco mais geral.