Eu li este artigo sobre o tópico, mas realmente não o entendo. Por favor, me dê alguns conselhos, juntamente com exemplos, ao descrever os conceitos.
Eu li este artigo sobre o tópico, mas realmente não o entendo. Por favor, me dê alguns conselhos, juntamente com exemplos, ao descrever os conceitos.
Respostas:
Java fornece dois tipos / classes diferentes de Objetos de Referência : forte e fraco . Objetos de referência fracos podem ser divididos em soft e phantom .
Vamos ponto por ponto.
Objeto de referência forte
StringBuilder builder = new StringBuilder();
Este é o tipo / classe padrão do Objeto de Referência, se não for especificado de forma diferente: builder
é um Objeto de Referência forte. Esse tipo de referência torna o objeto referenciado não qualificado para o GC. Ou seja, sempre que um objeto é referenciado por uma cadeia de objetos de referência fortes , ele não pode ser coletado como lixo.
Objeto de referência fraco
WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);
Objetos de referência fracos não são o tipo / classe padrão de Objeto de referência e, para serem usados, devem ser especificados explicitamente, como no exemplo acima. Esse tipo de referência torna o objeto de referência elegível para o GC. Ou seja, se a única referência alcançável para o StringBuilder
objeto na memória for, na verdade, a referência fraca, o GC poderá coletar o StringBuilder
objeto com lixo . Quando um objeto na memória é acessível apenas por Objetos de Referência Fracos, ele se torna automaticamente elegível para o GC.
Níveis de Fraqueza
Dois níveis diferentes de fraqueza podem ser alistados: suave e fantasma .
Um Objeto de Referência flexível é basicamente um Objeto de Referência fraco que permanece um pouco mais na memória: normalmente, resiste ao ciclo do GC até que não haja memória disponível e haja risco de OutOfMemoryError
(nesse caso, ele pode ser removido).
Por outro lado, um Objeto de Referência fantasma é útil apenas para saber exatamente quando um objeto foi efetivamente removido da memória: normalmente eles são usados para corrigir o comportamento estranho de finalização () de renascimento / ressurreição , já que eles realmente não retornam o objeto, mas apenas ajudam a acompanhar sua presença de memória .
Objetos de referência fracos são ideais para implementar módulos de cache. De fato, um tipo de despejo automático pode ser implementado, permitindo que o GC limpe as áreas de memória sempre que objetos / valores não forem mais alcançáveis por uma forte cadeia de referências. Um exemplo é o WeakHashMap que retém chaves fracas.
Referência fraca:
Uma referência fraca, simplificando, é uma referência que não é forte o suficiente para forçar um objeto a permanecer na memória. Referências fracas permitem que você aproveite a capacidade do coletor de lixo de determinar a acessibilidade para você, para que você não precise fazer isso sozinho.
Referência suave:
Uma referência suave é exatamente como uma referência fraca, exceto que é menos ansiosa para jogar fora o objeto ao qual se refere. Um objeto que é apenas fracamente acessível (as referências mais fortes a ele são WeakReferences) será descartado no próximo ciclo de coleta de lixo, mas um objeto que é fracamente acessível geralmente fica por um tempo.
Referência fantasma:
Uma referência fantasma é bem diferente de SoftReference ou WeakReference. A aderência ao objeto é tão tênue que você nem consegue recuperar o objeto - o método get () sempre retorna nulo. O único uso para essa referência é acompanhar quando é enfileirado em um ReferenceQueue, pois nesse momento você sabe que o objeto para o qual apontou está morto.
Este texto foi extraído de: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references
A simples diferença entre SoftReference
e WeakReference
é fornecida pelo Android Developer .
A diferença entre a SoftReference
e a WeakReference
é o ponto no tempo em que a decisão é tomada para limpar e enfileirar a referência:
A SoftReference
deve ser limpo e enfileirado o mais tarde possível, ou seja, no caso de a VM estar em risco de ficar sem memória.
A WeakReference
pode ser limpo e colocado na fila assim que se sabe que é pouco referenciado.
Os três termos que você usou estão relacionados principalmente à elegibilidade do objeto para obter o Garbage coletado.
Referência fraca :: É uma referência que não é forte o suficiente para forçar o objeto a permanecer na memória. São os caprichos do coletor de lixo coletar esse objeto para coleta de lixo. Você não pode forçar esse GC a não coletá-lo .
Referência suave : É mais ou menos o mesmo que a referência fraca. Mas você pode dizer que ele mantém o objeto um pouco mais forte do que a referência fraca da coleta de lixo.
Se os coletores de lixo coletarem a referência fraca no primeiro ciclo de vida, coletarão a referência flexível no próximo ciclo de coleta de lixo.
Referência Forte :: É exatamente o oposto dos dois tipos de referência acima. Eles são menos parecidos com a coleta de lixo (geralmente nunca são coletados).
Você pode consultar o seguinte link para obter mais informações:
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html
Este artigo pode ser super útil para entender referências fortes, suaves, fracas e fantasmas.
Para lhe dar um resumo,
Se você tiver uma referência forte a um objeto, ele nunca poderá ser coletado / recuperado pelo GC (Garbage Collector).
Se você tiver apenas referências fracas a um objeto (sem referências fortes), o objeto será recuperado pelo GC no próximo ciclo do GC.
Se você tiver apenas referências simples para um objeto (sem referências fortes), o objeto será recuperado pelo GC somente quando a JVM ficar sem memória.
Criamos referências fantasmas a um objeto para acompanhar quando o objeto é enfileirado no ReferenceQueue
. Depois que você souber que pode executar uma finalização refinada. (Isso evitaria que você ressuscitasse o objeto acidentalmente, pois a referência fantasma não fornece o referente). Eu sugiro que você leia este artigo para obter detalhes detalhados sobre isso.
Então, você pode dizer que referências fortes têm o poder máximo (nunca podem ser coletadas pelo GC)
Referências suaves são poderosas que referências fracas (pois podem escapar do ciclo do GC até a JVM ficar sem memória)
As referências fracas são ainda menos poderosas que as referências suaves (como elas não podem escapar de nenhum ciclo do GC e serão recuperadas se o objeto não tiver outra referência forte).
Analogia do restaurante
Agora, se você é um cliente forte (referência análoga a forte), mesmo que um novo cliente chegue ao restaurante ou algo que sempre aconteça, nunca sairá de sua mesa (a área de memória na pilha). O garçom não tem o direito de pedir para você (ou mesmo solicitar) para sair do restaurante.
Se você é um cliente flexível (semelhante à referência suave), se um novo cliente entrar no restaurante, o garçom não solicitará que você saia da mesa, a menos que não haja outra mesa vazia para acomodar o novo cliente. (Em outras palavras, o garçom solicitará que você saia da mesa apenas se um novo cliente entrar e não houver outra mesa para esse novo cliente)
Se você é um cliente fraco (referência análoga a fraca), o garçom, por sua vontade, pode (a qualquer momento) pedir para você sair do restaurante: P
4 graus de referência - Strong, Weak, Soft, Phantom
Forte - é um tipo de referência, que torna o objeto referenciado não elegível para o GC. classes de construtor. por exemplo - StringBuilder
Fraco - é uma referência qualificada para GC.
Suave - é um tipo de referência cujo objeto é elegível para GC até que a memória esteja disponível. Melhor para cache de imagens. Ele irá mantê-los até que a memória esteja disponível.
Fantasma - é um tipo de referência cujo objeto é diretamente qualificado para GC. Usado apenas para saber quando um objeto é removido da memória.
usa:
Permite identificar quando um objeto é exatamente removido da memória.
quando o
finalize()
método está sobrecarregado, o GC pode não ocorrer em tempo hábil para objetos elegíveis para o GC das duas classes. Portanto, a referência fantasma os torna elegíveis para o GC antesfinalize()
; é por isso que você pode obter OutOfMemoryErrors mesmo quando a maior parte do heap é lixo.
Referências fracas são ideais para implementar os módulos de cache.
Estas são suas referências regulares a objetos que codificamos diariamente:
Employee emp = new Employee();
A variável "emp" mantém uma forte referência a um objeto Employee, e os objetos que podem ser acessados por qualquer cadeia de referências fortes não são elegíveis para a coleta de lixo. Normalmente, é isso que você deseja, mas nem sempre. Agora, suponha que estamos buscando muitos funcionários do banco de dados em uma coleção ou mapa, e precisamos fazer muito processamento regularmente, portanto, para manter o desempenho, mantê-los no cache.
Na medida em que isso é bom, mas agora precisamos de dados diferentes e não precisamos desses objetos Employee e eles não são referenciados de nenhum lugar, exceto o cache. O que está causando um vazamento de memória porque esses objetos não estão em uso, mas ainda não são elegíveis para a coleta de lixo e não podemos removê-los do cache porque não temos referência a eles? Então aqui precisamos esvaziar manualmente todo o cache, o que é entediante ou poderíamos usar outras referências de tipo, por exemplo, Referências Fracas.
Uma referência fraca não prende um objeto na memória e será gerada pelo GC no próximo ciclo do GC, se não for referenciada por outras referências. Podemos usar a classe WeakReference, que é fornecida pelo Java, para criar os tipos de caches acima, que não armazenam objetos que não são referenciados em outro lugar.
WeakReference<Cache> cache = new WeakReference<Cache>(data);
Para acessar os dados, você precisa chamar cache.get (). Essa chamada para obter pode retornar nulo se a referência fraca foi coletada como lixo: você deve verificar o valor retornado para evitar NPEs. Java fornece coleções que usam referências fracas, por exemplo, a classe WeakHashMap armazena chaves (não valores) como referências fracas. Se a chave for GC'd, o valor também será removido automaticamente do mapa.
Como referências fracas também são objetos, precisamos de uma maneira de limpá-las (elas não são mais úteis quando o objeto ao qual estavam fazendo referência foi submetido ao GC). Se você passar um ReferenceQueue para o construtor para uma referência fraca, o coletor de lixo anexará essa referência fraca ao ReferenceQueue antes que eles sejam finalizados ou com GC. Você pode processar periodicamente essa fila e lidar com referências inativas.
Um SoftReference é como um WeakReference, mas é menos provável que seja coletado como lixo. As referências suaves são limpas a critério do coletor de lixo em resposta à demanda de memória. A máquina virtual garante que todas as referências suaves a objetos facilmente alcançáveis tenham sido limpas antes de lançar um OutOfMemoryError.
Referências fantasmas são os mais fracos de todos os tipos de referência, chamando get nelas sempre retornará nulo. Um objeto é phantomly referenciado após ter sido finalizado, mas antes de sua memória alocada ter sido recuperada, ao contrário de referências fracas que são enfileiradas antes de serem finalizadas ou referências Phantom da GC raramente são usadas.
Então, como eles são úteis? Quando você constrói uma referência fantasma, sempre deve passar um ReferenceQueue. Isso indica que você pode usar uma referência fantasma para ver quando seu objeto está no GC.
Ei, se referências fracas forem enfileiradas quando consideradas consideradas finalizadas, mas ainda não estiverem no GC, poderíamos criar uma nova referência forte para o objeto no bloco finalizador e impedir que o objeto fosse GC. Sim, você pode, mas provavelmente não deveria fazer isso. Para verificar esse caso, o ciclo do GC ocorrerá pelo menos duas vezes para cada objeto, a menos que esse objeto seja alcançável apenas por uma referência fantasma. É por isso que você pode ficar sem pilha mesmo que sua memória contenha bastante lixo. Referências fantasmas podem impedir isso.
Você pode ler mais no meu artigo Tipos de referências em Java (forte, suave, fraco, fantasma) .