A única coisa que sei PhantomReference
é,
- Se você usar seu
get()
método, ele sempre retornaránull
e não o objeto. Qual é a utilidade disso? - Ao usar
PhantomReference
, você garante que o objeto não pode ser ressuscitado dofinalize
método.
Mas qual é a utilidade desse conceito / classe?
Você já usou isso em algum de seu projeto ou tem algum exemplo onde devemos usar isso?
FakeReference
ouNonReference
.Respostas:
Usei
PhantomReference
s em um tipo de perfil de memória simplista e muito especializado para monitorar a criação e destruição de objetos. Eu precisava deles para controlar a destruição. Mas a abordagem está desatualizada. (Foi escrito em 2004 com o objetivo de J2SE 1.4.) As ferramentas de criação de perfis profissionais são muito mais poderosas e confiáveis e os recursos Java 5 mais recentes, como JMX ou agentes e JVMTI, também podem ser usados para isso.PhantomReference
s (sempre usados junto com a fila de referência) são superiores aosfinalize
que apresentam alguns problemas e, portanto, devem ser evitados. Principalmente tornando os objetos acessíveis novamente. Isso poderia ser evitado com o idioma do guardião do finalizador (-> leia mais em 'Java Efetivo'). Portanto, eles também são o novo finalize .Além disso,
PhantomReference
sE como o psd escreveu primeiro, Roedy Green tem um bom resumo de referências .
fonte
Uma explicação geral sobre a tabela dividida , do Glossário Java.
Que, claro, coincide com a documentação PhantomReference :
E por último, mas não menos importante, todos os detalhes sangrentos ( esta é uma boa leitura ): Objetos de referência Java (ou como eu aprendi a parar de se preocupar e amar OutOfMemoryError) .
Boa codificação. (Mas para responder à pergunta, eu só usei WeakReferences.)
fonte
Ótima explicação sobre o uso de Phantom Reference:
fonte
Eu encontrei um caso prático e útil uso do
PhantomReference
que éorg.apache.commons.io.FileCleaningTracker
no projeto commons-io.FileCleaningTracker
irá excluir o arquivo físico quando seu objeto marcador for coletado como lixo.Algo a se notar é a
Tracker
classe que estende aPhantomReference
classe.fonte
ISTO DEVE SER OBSOLETO COM JAVA 9!
Use em seu
java.util.Cleaner
lugar! (Ousun.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:
E há o método ainda mais simples de fechamento automático, que faz quase o mesmo que o anterior:
Para responder às suas perguntas:
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.
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.
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.
fonte
Usei um PhantomReference em um teste de unidade para verificar se o código em teste não mantinha referências desnecessárias a algum objeto. ( Código original )
E o teste :
fonte
É comum usar
WeakReference
ondePhantomReference
é mais apropriado. Isso evita certos problemas de ser capaz de ressuscitar objetos depois que umWeakReference
é limpo / enfileirado pelo coletor de lixo. Normalmente, a diferença não importa porque as pessoas não estão brincando de besteira.Usar
PhantomReference
tende a ser um pouco mais intrusivo porque você não pode fingir que oget
método funciona. Você não pode, por exemplo, escrever umPhantom[Identity]HashMap
.fonte
weakref.get
poderia retornarnull
e, mais tarde, ainda é capaz de retornar o obj?finalize
não recria o objeto como tal. Ele pode fazer o objeto fortemente acessível novamente depois deWeakReference
retornosnull
deget
e é enfileirado. / (user166390: Como em um mapa digitado no alvo da referência, comoWeakHashMap
faz, não um mapa de identidade de referências, o que é bom.)Os métodos úteis para chamar (em vez de
get()
) seriamisEnqueued()
oureferenceQueue.remove()
. Você chamaria esses métodos para executar alguma ação que precisa ocorrer na rodada final da coleta de lixo do objeto.A primeira vez é quando o objeto tem seu
finalize()
método chamado, então você pode colocar ganchos de fechamento lá também. No entanto, como outros afirmaram, provavelmente há maneiras mais seguras de realizar a limpeza ou qualquer ação que precise ocorrer antes e depois da coleta de lixo ou, de modo mais geral, no final da vida útil do objeto.fonte
Eu encontrei outro uso prático de
PhantomReferences
na classe LeakDetector do Jetty.Jetty usa a
LeakDetector
classe para detectar se o código do cliente adquire um recurso, mas nunca o libera, e aLeakDetector
classe usa oPhantomReferences
para esse propósito.fonte