Qual é a diferença entre java.lang.ref.WeakReference
e java.lang.ref.SoftReference
?
java
reference
weak-references
soft-references
driekken
fonte
fonte
Respostas:
From Understanding Weak References , de Ethan Nicholas:
E Peter Kessler acrescentou em um comentário:
fonte
Referências fracas são coletadas ansiosamente. Se o GC descobrir que um objeto é fracamente acessível (acessível apenas por referências fracas), ele limpará as referências fracas a esse objeto imediatamente. Como tal, eles são bons para manter uma referência a um objeto para o qual seu programa também mantém (fortemente referenciadas) "informações associadas" em algum lugar, como informações de reflexão em cache sobre uma classe ou um invólucro para um objeto, etc. não faz sentido manter o objeto associado ao GC-ed. Quando a referência fraca é limpa, ela é enfileirada em uma fila de referência que seu código pesquisa em algum lugar, além de descartar os objetos associados. Ou seja, você mantém informações extras sobre um objeto, mas essas informações não são necessárias quando o objeto a que ele se refere desaparece. Na realidade, em determinadas situações, você pode até subclassificar WeakReference e manter as informações extras associadas sobre o objeto nos campos da subclasse WeakReference. Outro uso típico do WeakReference é em conjunto com o Maps para manter instâncias canônicas.
As SoftReferences, por outro lado, são boas para armazenar em cache recursos externos recreativos, pois o GC normalmente atrasa a limpeza. É garantido, no entanto, que todas as SoftReferences serão limpas antes da saída do OutOfMemoryError, portanto, teoricamente, elas não podem causar um OOME [*].
O exemplo típico de caso de uso é manter uma forma analisada de um conteúdo de um arquivo. Você implementaria um sistema no qual carregaria um arquivo, analisaria e manteria um SoftReference no objeto raiz da representação analisada. Da próxima vez que você precisar do arquivo, tente recuperá-lo através do SoftReference. Se você pode recuperá-lo, poupou-se de outra carga / análise e, se o GC o limpou nesse meio tempo, você o recarregou. Dessa forma, você utiliza memória livre para otimização de desempenho, mas não arrisca um OOME.
Agora para o [*]. Manter um SoftReference não pode causar um OOME em si. Se, por outro lado, você usa o SoftReference por engano para uma tarefa que um WeakReference deve ser usado (a saber, você mantém as informações associadas a um Objeto de alguma forma fortemente referenciadas e as descarta quando o objeto de Referência é limpo), você pode executar o OOME como seu código que pesquisa o ReferenceQueue e descarta os objetos associados pode não ser executado em tempo hábil.
Portanto, a decisão depende do uso - se você estiver armazenando em cache informações que são caras de construir, mas mesmo assim reconstrutíveis a partir de outros dados, use referências flexíveis - se você estiver mantendo uma referência a uma instância canônica de alguns dados ou desejar tenha uma referência a um objeto sem "possuí-lo" (impedindo-o de ser GC'd), use uma referência fraca.
fonte
WeakReference
é que, em locais onde a pessoa deve usá-la, o fato de permanecer válido por um tempo após a referência sair do escopo pode ser tolerável, mas não é desejável.WeakReference
para observar as execuções do GC. Veja elaboração: stackoverflow.com/a/46291143/632951Em Java ; ordem do mais forte para o mais fraco, existem: Forte, Suave, Fraco e Fantasma
Uma referência Forte é uma referência normal que protege o objeto referido da coleção pelo GC. ou seja, nunca coleta lixo.
Uma referência suave é qualificada para coleta pelo coletor de lixo, mas provavelmente não será coletada até que sua memória seja necessária. ou seja, o lixo é coletado antes
OutOfMemoryError
.Uma referência fraca é uma referência que não protege um objeto referenciado da coleção pelo GC. ou seja, o lixo é coletado quando não há referências de Forte ou Macio.
Uma referência fantasma é uma referência a um objeto que é referenciada fantasmamente após sua finalização, mas antes de sua memória alocada ter sido recuperada.
Fonte
Analogia: Suponha que uma JVM é um reino, Object é um rei do reino e GC é um atacante do reino que tenta matar o rei (objeto).
fonte
until memory is available
não faz sentido. Você quer dizeris eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use
?Referência fraca http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html
Princípio:
weak reference
está relacionado à coleta de lixo. Normalmente, objeto com um ou maisreference
não será elegível para coleta de lixo.O princípio acima não é aplicável quando é
weak reference
. Se um objeto tiver apenas uma referência fraca com outros objetos, estará pronto para a coleta de lixo.Vejamos o exemplo abaixo: Temos um
Map
com objetos onde Key é referência a um objeto.Agora, durante a execução do programa que fizemos
emp = null
. AMap
realização a chave não faz sentido aqui como énull
. Na situação acima, o objeto não é coletado como lixo.WeakHashMap
WeakHashMap
é aquele em que as entradas (key-to-value mappings
) serão removidas quando não for mais possível recuperá-las doMap
.Deixe-me mostrar o exemplo acima mesmo com o WeakHashMap
Saída: levou
20 calls to System.gc()
para resultar emaMap size
: 0.WeakHashMap
tem apenas referências fracas às chaves, não referências fortes como outrasMap
classes. Há situações em que você deve tomar cuidado quando o valor ou a chave é fortemente referenciado, embora você tenha usadoWeakHashMap
. Isso pode ser evitado envolvendo o objeto em um WeakReference .Referências suaves.
Soft Reference
é um pouco mais forte que a referência fraca. A referência suave permite a coleta de lixo, mas pede ao coletor de lixo que a limpe apenas se não houver outra opção.O coletor de lixo não coleta agressivamente objetos de fácil acesso, como ocorre com objetos de fácil acesso - em vez disso, apenas coleta objetos de fácil acesso se realmente "precisar" da memória. Referências suaves são uma maneira de dizer ao coletor de lixo: "Enquanto a memória não estiver muito tensa, eu gostaria de manter esse objeto por perto. Mas se a memória ficar muito tensa, vá em frente e colete-a, e eu resolvo com isso." O coletor de lixo é necessário para limpar todas as referências suaves antes que ele possa ser lançado
OutOfMemoryError
.fonte
NullPointerException
noaMap.get().put(...)
.WeakHashMap
exemplo (já que esse é o primeiro que está demonstrando comportamento fraco). Veja o documento para "WeakHashMap":"An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. "
O ponto principal de usar o WeakHashMap é que você não precisa declarar / passar um WeakReference; o WeakHashMap faz isso por você, internamente. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.htmlWeakHashMap
em ação, com o exemplo de aplicativo mostrando como as entradas são removidas somente após a execução da coleta de lixo, consulte minha Resposta à pergunta: O WeakHashMap está sempre crescendo ou limpa as chaves do lixo? .A única diferença real entre uma referência suave e uma referência fraca é que
fonte
SoftReference
foi projetado para caches. Quando for descoberto que um fazWeakReference
referência a um objeto inacessível, ele será limpo imediatamente.SoftReference
pode ser deixado como está. Normalmente, existe algum algoritmo relacionado à quantidade de memória livre e ao tempo usado pela última vez para determinar se ela deve ser limpa. O algoritmo atual da Sun é limpar a referência se ela não for usada em tantos segundos quanto houver megabytes de memória livre no heap Java (configurável, o HotSpot do servidor verifica o heap máximo possível, conforme definido por-Xmx
).SoftReference
s serão limpos antes deOutOfMemoryError
serem lançados, a menos que seja alcançável de outra forma.fonte
java.lang
. Tal abuso de sinônimos não está fazendo bem a ninguém.Este artigo pode ser super útil para entender referências fortes, suaves, fracas e fantasmas.
Para lhe dar um resumo,
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.
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)
Referências fracas são ainda menos poderosas que as referências flexíveis (como não podem exceder 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 o que quer que seja, nunca sairá da sua mesa (a área de memória na pilha). O garçom não tem o direito de pedir para você (ou até 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
fonte
A Única Diferença Real
De acordo com o documento , as WeakReferences frouxas devem ser limpas por um GC em execução.
De acordo com o documento , as SoftReferences soltas devem ser limpas antes que o OOM seja lançado.
Essa é a única diferença real. Tudo o resto não faz parte do contrato. (Presumo que os documentos mais recentes sejam contratuais.)
SoftReferences são úteis. Os caches sensíveis à memória usam SoftReferences, não WeakReferences.
O único uso adequado do WeakReference é observar a execução do GC. Você faz isso criando um novo WeakReference cujo objeto fica imediatamente fora do escopo e tenta sair nulo
weak_ref.get()
. Quando énull
, você aprende que, entre essa duração, o GC foi executado.Quanto ao uso incorreto do WeakReference, a lista é interminável:
um truque ruim para implementar a softreferência de prioridade 2, de modo que você não precise escrever uma, mas não funciona conforme o esperado, porque o cache seria limpo a cada execução do GC, mesmo quando houver memória disponível. Consulte https://stackoverflow.com/a/3243242/632951 para obter phails. (Além disso, e se você precisar de mais de 2 níveis de prioridade de cache? Você ainda precisará de uma biblioteca real para isso.)
um péssimo hack para associar dados a um objeto de uma classe existente, mas cria um vazamento de memória (OutOfMemoryError) quando o seu GC decide fazer uma pausa após a criação de suas fracas referências. Além disso, é muito feio: uma abordagem melhor é usar tuplas.
um truque ruim para associar dados a um objeto de uma classe existente, em que a classe tem a coragem de se tornar não subclassável e é usada em um código de função existente que você precisa chamar. Nesse caso, a solução adequada é editar a classe e torná-la subclassável, ou editar a função e fazer com que ela use uma interface em vez de uma classe ou use uma função alternativa.
fonte
equals()
é apenas identidade do objeto? Referências suaves parecem um desperdício lá, porque uma vez que um objeto-chave não é mais alcançável, ninguém mais procurará esse mapeamento.Os seis tipos de estados de acessibilidade de objetos em Java:
Para mais detalhes: https://www.artima.com/insidejvm/ed2/gc16.html «recolher
fonte
Deve-se estar ciente de que um objeto com pouca referência só será coletado quando tiver APENAS referências fracas. Se tiver apenas uma referência forte, ele não será coletado, não importa quantas referências fracas tenha.
fonte
Para dar um aspecto de uso da memória em ação, fiz um experimento com referências Forte, Suave, Fraca e Fantasma sob carga pesada com objetos pesados, mantendo-as até o final do programa. Em seguida, monitorou o uso de heap e o comportamento do GC . Essas métricas podem variar caso a caso, mas certamente oferecem um alto nível de entendimento. Abaixo estão os resultados.
Heap e comportamento do GC sob carga pesada
Você pode obter gráficos mais detalhados , estatísticas, observações para este experimento aqui .
fonte
WeakReference : objetos que são pouco referenciados são coletados a cada ciclo do GC (menor ou completo).
SoftReference : quando objetos que são apenas referenciados suavemente são coletados depende de:
-XX: SoftRefLRUPolicyMSPerMB = N sinalizador (o valor padrão é 1000, ou seja, 1 segundo)
Quantidade de memória livre na pilha.
Exemplo:
O objeto referenciado apenas pelo SoftReference será coletado se a última vez em que foi acessada for maior que 10 segundos.
fonte