Se um objeto na memória não tiver referência, significa que o objeto não é mais usado e pode se tornar um candidato à coleta de lixo. No entanto, como o tempo de execução do coletor de lixo é incerto, o tempo real de reciclagem dos objetos que podem ser coletados de lixo é incerto. Para um objeto, desde que haja uma referência, ele sempre existirá na memória. Se houver mais e mais objetos como esse, excedendo a memória total na JVM, a JVM apresentará um erro de memória. Embora a operação específica da coleta de lixo seja controlada pela JVM, os desenvolvedores ainda podem interagir com o coletor de lixo até certo ponto, e o objetivo é ajudar melhor o coletor de lixo a gerenciar a memória do aplicativo. Esse método de interação é usar o pacote java.lang.ref introduzido pelo JDK 1.2.
1 Citação forte
Citações fortes são as citações mais comuns usadas. Se um objeto tiver uma referência forte, o coletor de lixo nunca o reciclará. Quando o espaço de memória é insuficiente, a máquina virtual Java prefere lançar um erro de MemoryError para fazer com que o programa termine anormalmente e não reciclaria objetos com fortes referências para resolver o problema da memória insuficiente.
Por exemplo, data date = new Date (), a data é uma forte referência a um objeto. Referências fortes a objetos podem ser passadas em toda parte do programa. Em muitos casos, várias referências apontarão para o mesmo objeto ao mesmo tempo. A existência de referências fortes limita o tempo de sobrevivência de um objeto na memória. Se o objeto A contiver uma forte referência ao objeto B, em geral, o tempo de sobrevivência do objeto B não será mais curto que o objeto A. Se o objeto A não definir explicitamente a referência do objeto B como nulo, somente depois que o objeto A é coletado de lixo, o objeto B não terá mais uma referência apontando para ele, e será possível obter a oportunidade de ser coletado de lixo.
Exemplo Código:
pacote com.skywang.java; public class fortReferenceTest {public static void main (string [] args) {mydate date = new mydate (); System.gc (); }} Resultados em execução:
<Sem saída>
O resultado mostra que, embora a coleta de lixo seja chamada explicitamente, é uma forte referência para a data e a data não é reciclada.
Além de referências fortes, o pacote java.lang.ref fornece métodos de referência diferentes para um objeto. O coletor de lixo da JVM tem diferentes maneiras de lidar com diferentes tipos de referências.
2 citações suaves
Se um objeto tiver apenas referências suaves, o espaço de memória é suficiente e o coletor de lixo não o reciclará; Se o espaço de memória for insuficiente, a memória desses objetos será reciclada. Enquanto o coletor de lixo não o reciclar, o objeto poderá ser usado pelo programa. Referências suaves podem ser usadas para implementar caches sensíveis à memória.
Uma referência suave pode ser usada em conjunto com uma fila de referência (ReferenceQueue). Se o objeto referenciado pela referência soft for reciclado pelo coletor de lixo, a máquina virtual Java adicionará a referência suave à fila de referência associada.
As referências suaves são mais fracas que as referências fortes em força e são representadas por softreference. Sua função é dizer ao coletor de lixo que objetos no programa são menos importantes e podem ser temporariamente reciclados quando houver memória insuficiente. Quando não houver memória insuficiente na JVM, o coletor de lixo liberará objetos que são apontados apenas por referências suaves. Se todos esses objetos forem lançados e a memória for insuficiente, um erro de Memória ou seja lançado. Referências suaves são ideais para criar caches. Quando o sistema é insuficiente, o conteúdo do cache pode ser liberado. Por exemplo, considere um programa de editor de imagens. O programa lerá todo o conteúdo do arquivo de imagem na memória para facilitar o processamento. Os usuários também podem abrir vários arquivos ao mesmo tempo. Quando há muitos arquivos abertos ao mesmo tempo, isso pode causar memória insuficiente. Se as referências suaves forem usadas para apontar para o conteúdo do arquivo de imagem, o coletor de lixo poderá recuperar essa memória quando necessário.
Exemplo Código:
pacote com.skywang.java; importar java.lang.ref.softReference; public class SoftReferenceTest {public static void main (string [] args) {softreference ref = new softreference (new mydate ()); ReferenceCetest.DrainMemory (); }} Resultados em execução:
<Sem saída>
Resultados: Quando a memória é insuficiente, a referência suave é encerrada. Quando referências suaves são proibidas,
SOFTRREFERECE REF = nova Softreference (new MyDate ()); referenceCetest.DrainMemory ();
Equivalente a
Mydate data = new mydate (); // Cabe à JVM executar se (jvm. insuficiente memória ()) {date = null; System.gc ();} 3 citações fracas
A referência fraca é mais fraca que a referência suave em força e é expressa pela classe de referência fraca. Seu objetivo é se referir a um objeto, mas não impede que o objeto seja reciclado. Se uma referência forte for usada, desde que exista referência, o objeto referenciado não poderá ser reciclado. Citações fracas não têm esse problema. Quando o coletor de lixo estiver em execução, se todas as referências a um objeto forem referências fracas, o objeto será reciclado. A função de referências fracas é resolver a relação de acoplamento entre objetos no tempo de sobrevivência provocada por fortes referências. O uso mais comum de referências fracas é nas aulas de coleta, especialmente nas tabelas de hash. A interface da tabela de hash permite que qualquer objeto Java seja usado como chave. Quando um par de valores-chave é colocado na tabela de hash, o próprio objeto da tabela de hash tem uma referência a esses objetos de chave e valor. Se essa referência for uma referência forte, desde que o objeto da tabela de hash ainda esteja vivo, a chave e os objetos de valor contidos nele não serão reciclados. Se uma tabela de hash com um longo tempo de sobrevivência contiver muitos pares de valor-chave, pode eventualmente consumir toda a memória na JVM.
A solução para essa situação é usar referências fracas para referenciar esses objetos para que os objetos de chave e valor na tabela de hash possam ser coletados de lixo. O fracashashmap é fornecido em Java para atender a essa necessidade comum.
Código de exemplo:
pacote com.skywang.java; importar java.lang.ref.weakReference; public class fracyReferenceTest {public static void main (string [] args) {fracas referência = nova referência fraca (new mydate ()); System.gc (); }} Resultados em execução:
OBJ [Data: 1372142034360] é GC
Resultados: Quando a coleta de lixo da JVM é executada, as referências fracas são encerradas.
Referência fraca referência = nova fraca referência (new mydate ()); System.gc ();
Equivalente a:
Mydate data = new mydate (); // coleta de lixo if (jvm. insuficiente memória ()) {date = null; System.gc ();} A diferença entre referências fracas e referências suaves é que objetos apenas com referências fracas têm um ciclo de vida mais curto. Durante o processo de um fio de coletor de lixo que digitaliza a área de memória sob sua jurisdição, uma vez que um objeto com apenas referências fracas for encontrado, sua memória será reciclada, independentemente de o espaço atual de memória ser suficiente ou não. No entanto, como o coletor de lixo é um fio com prioridade muito baixa, ele pode não ser necessariamente descoberto rapidamente para objetos que apenas têm referências fracas.
Uma referência fraca pode ser usada em conjunto com uma fila de referência (ReferenceQueue). Se o objeto referenciado por uma referência fraca for coletada de lixo, a máquina virtual Java adicionará a referência fraca à fila de referência associada.
4 citações de ilusão
Também conhecido como Ghost Quotes ~ Antes de introduzir citações fantasmas, devemos primeiro apresentar o mecanismo de terminação de objetos fornecido por Java. Existe um método finalizado na classe de objeto. A intenção original de seu design é realizar algum trabalho de limpeza antes que um objeto seja realmente reciclado. Como o Java não fornece um mecanismo semelhante ao destruidor de C ++, ele é implementado através do método finalizado. Mas o problema é que o tempo de execução do coletor de lixo não é corrigido; portanto, o tempo de execução real desses trabalhos de limpeza não pode ser previsto. Uma referência fantasma pode resolver esse problema. Ao criar uma fantasma de referência fantasma, você deve especificar uma fila de referência. Quando o método finalizado de um objeto for chamado, a referência fantasma do objeto será adicionada à fila. Ao verificar o conteúdo na fila, você saberá se um objeto está pronto para ser reciclado.
O uso de referências fantasmas e suas filas é raro e é usado principalmente para implementar o controle de uso de memória relativamente fino, o que é muito significativo para dispositivos móveis. O programa pode solicitar memória para criar um novo objeto após determinar que um objeto deve ser reciclado. Dessa forma, a memória consumida pelo programa pode ser mantida em uma quantidade relativamente baixa.
Por exemplo, o código a seguir fornece um exemplo da implementação de um buffer.
classe pública phantombuffer {private byte [] dados = novo byte [0]; Referência privadaqueue <byte []> fila = new ReferenceQueue <byte []> (); Phantomreference privado <byte []> ref = new Phantomreference <byte []> (dados, fila); public byte [] get (int size) {if (size <= 0) {lança novo ilegalArgumentException ("tamanho do buffer errado"); } if (data.length <size) {data = null; System.gc (); // Força execute o coletor de lixo Tente {Queue.remove (); // Este método será bloqueado até que a fila seja ref.clear (); // A referência do fantasma não será limpa automaticamente, você deve executar ref = null; dados = novo byte [tamanho]; Ref = nova fantasma -referência <byte []> (dados, fila); } catch (interruptedException e) {e.printStackTrace (); }} retornar dados; }} No código acima, toda vez que um novo buffer é aplicado, é garantido que a matriz de bytes do buffer anterior foi reciclada com sucesso. O método de remoção que faz referência à fila bloqueará até que uma nova referência fantasma seja adicionada à fila. No entanto, deve -se notar que essa abordagem fará com que o coletor de lixo seja executado muitas vezes, o que pode fazer com que o programa seja muito baixo.
Código de exemplo:
pacote com.skywang.java; importar java.lang.ref.referencequeue; importar java.lang.ref.phantomreference; public class Phantomreference Ref = New Phantomreference (new MyDate (), fila); System.gc (); }}
Resultados em execução:
OBJ [DATA: 1372142282558] é GC
O resultado mostra que a referência da ilusão é terminada após a instanciação.
ReferenceQueue fila = new ReferenceQueue (); Phantomreference Ref = New Phantomreference (new MyDate (), fila); System.GC ();
Equivalente a:
Mydate data = new mydate (); date = null;