Java: diferença entre referência forte / suave / fraca / fantasma

178

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.

Matthias Braun
fonte
4
Eu li esse documento, não me ajuda a imaginar que diferença. (talvez por ser um documento de leitura difícil) #
14
Se você leu esse artigo e ainda não entende, você tem perguntas específicas sobre ele? É difícil responder a "por favor, explique-me Foo", "aqui está o que significa", "eu não entendo", sem detalhes sobre quais partes você não recebe.
precisa saber é
@LouisWasserman O link superior não é mais válido.
Mehraj Malik

Respostas:

142

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 .

  • Forte
  • Fraco
    • suave
    • fantasma

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 StringBuilderobjeto na memória for, na verdade, a referência fraca, o GC poderá coletar o StringBuilderobjeto 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.

Paolo Maresca
fonte
76

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

Punith Raj
fonte
1
Embora tudo nesta resposta pareça correto, também me parece que pode haver um erro na página vinculada. O Javadoc para o pacote java.lang.ref e o PhantomReference sugerem que um objeto não é coletado como lixo até que ele não seja mais "phantom alcançável", implicando que (ao contrário do SoftReference) um PhantomReference deve ser desenfileirado antes que o objeto ao qual ele se refere possa ser lixo coletado ... e seu enfileiramento não indica que a memória associada foi liberada.
Theodore Murdock
2
Para o registro, eu preferiria morar em um mundo em que a postagem do blog esteja correta.
Theodore Murdock
1
@TheodoreMurdock O javadoc está correto. Uma referência fantasma não impede a coleta de lixo. Depois que um objeto é enfileirado, ele não pode ser salvo nem por um finalizador, pois os finalizadores já foram executados. Está morto, mas ainda não se foi.
Leliel 01/03
@Leliel Na verdade, uma referência fantasma faz na verdade coleção impedem de lixo depois que ele é enfileirado ... Percebi isso recentemente, quando um erro causou um segmento de limpeza a saída precoce. A existência de referências fantasmas foi suficiente para garantir que todos os objetos referenciados fantasmas fossem retidos no meu despejo de heap, indisponíveis para coleta ... se você não conseguir processar a fila ou não tornar a referência fantasma elegível para gc ao processar a fila ( e não limpe () a referência fantasma), o vazamento de memória incluirá a referência fantasma e o objeto referenciado.
Theodore Murdock
25

A simples diferença entre SoftReferencee WeakReferenceé fornecida pelo Android Developer .

A diferença entre a SoftReferencee a WeakReferenceé o ponto no tempo em que a decisão é tomada para limpar e enfileirar a referência:

  • A SoftReferencedeve 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 WeakReferencepode ser limpo e colocado na fila assim que se sabe que é pouco referenciado.

Muhammad Nabeel Arif
fonte
16

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

Sabya
fonte
3
Eu acho que isso está errado - "Se os coletores de lixo coletarem a referência fraca no primeiro ciclo de vida, eles coletarão a referência suave no próximo ciclo de coleta de lixo". Não é necessariamente assim, como você pode ter tanta certeza de que eles ocorrem na execução consecutiva do GC? O GC pode permitir que objetos referenciados permaneçam vivos mesmo na 2ª e na 3ª séries. Não há documentação para isso, se houver, mencione o link especificando.
Saurabh Patil
2
Além disso, sua resposta é um pouco vaga, veja esta frase 'É mais ou menos igual à 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. - ele está claramente perguntando sobre a diferença e não as semelhanças, todas essas palavras acrescentam mais confusão do que clareza ao tópico.
Saurabh Patil
@SaurabhPatil - Perdeu o seu comentário. Aqui estão as respostas. 1. "ele está perguntando claramente sobre a diferença e não as semelhanças" - Consulte a descrição da pergunta (não "apenas" o título) "Por favor, dê-me alguns conselhos e por favor, dê-me um exemplo para descrever". 2. "Mas você pode dizer que ele mantém o objeto um pouco mais ...." Eu acho que o SOF dá uma opção para fazer votos negativos e também dar novas respostas.
Sabya
14

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

  • Garçom - GC
  • Você - Objeto na pilha
  • Área / espaço para restaurantes - Espaço de pilha
  • Novo cliente - novo objeto que deseja tabela no 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

Lavish Kothari
fonte
10

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:

  1. Permite identificar quando um objeto é exatamente removido da memória.

  2. 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 antes finalize(); é 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.

Preetham RU
fonte
10

Referências Fortes

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.

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.

Referências suaves

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

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) .

Naresh Joshi
fonte
você escreveu que as referências fracas serão submetidas à GC no próximo ciclo, se não forem referenciadas a partir de outras referências ... mas não deve acontecer a mesma coisa com as referências de stron? se a stron refrence não for acessada de forma alguma, ela será limpa ... então, se sim, onde está a diferença novamente ...? #confused
filemonczyk
1
Se um objeto está sendo referido, digamos s1 (forte) e s2 (forte), o objeto não será elegível para coleta de lixo até que s1 e s2 sejam desreferenciados, mas se o objeto estiver sendo referido de s1 (fraco) e s2 ( forte), o objeto será elegível para a coleta de lixo no próximo ciclo da GC quando for desreferenciado apenas de s2, porque s1 é uma referência fraca e se o objeto não tiver outra referência, exceto a fraca, é elegível para a GC
Naresh Joshi