Existem quatro tipos de referência em Java/Android, a saber:
Referência forte - forte referência
Referência suave - referência suave
Referência fraca - referência fraca
Phantom Reference - Citação virtual
Diferentes tipos de referência têm características diferentes e também correspondem a diferentes cenários de uso.
1. Referência Stong - Referência forte
O tipo mais comum de referência na codificação real. Formas comuns como: a a = novo a (); etc. A forte referência em si é armazenada na memória da pilha e armazena o endereço no objeto na memória. Geralmente, quando não há mais referência forte ao objeto na memória apontando para ele, a máquina de coleta de lixo começa a considerar a coleta de lixo que pode ser feita nessa memória. Se codificar: a = nulo, neste momento, o endereço que foi alocado apenas na pilha e criado não tem outras referências. Quando o sistema executa a coleta de lixo, a memória da pilha será coletada de lixo.
Softreference, fracos e referência fantasma são todas subclasses da classe java.lang.ref.reference. A referência, como uma classe base abstrata, define as operações básicas de seus objetos de subclasse. As subclasses de referência têm as seguintes características:
1. A subclasse de referência não pode ser criada diretamente sem parametrização. Ele deve pelo menos usar o forte objeto de referência como parâmetro de construção para criar seus respectivos objetos de subclasse;
2. Como o objeto é criado em 1 com o forte objeto de referência como parâmetro de construção, os objetos na memória da heap apontados pela referência originalmente forte não estarão mais diretamente relacionados à forte referência, mas também terão uma certa conexão com a referência do objeto de subclasse de referência. E essa conexão pode afetar a coleta de lixo do objeto.
De acordo com as diferentes características de influência de diferentes objetos de subclasse na coleta de lixo de seus objetos indicadores (fortes referências a objetos na memória da heap apontados), três subclasses são formadas, a saber, SoftReference, fracos e referência fantasma.
2.Soft Referência - Referência Soft
A forma de uso geral de referência suave é a seguinte:
A a = novo a ();
Softreference <a> sra = nova softreference <a> (a);
Através da forte referência do objeto como um parâmetro, um objeto Softreference é criado e o WRA na memória da pilha aponta para esse objeto.
Neste momento, a seguinte codificação é realizada: a = nulo. Que impacto isso tem na coleta de lixo do objeto A originalmente apontado por A?
Vamos dar uma olhada nos resultados da saída do seguinte programa:
importar java.lang.ref.softreference; public class referenceCetest {public static void main (string [] args) {a a = new a (); Softreference <a> sra = nova softreference <a> (a); a = nulo; if (sra.get () == null) {System.out.println ("Um objeto entra no processo de coleta de lixo"); } else {System.out.println ("Um objeto ainda não foi reciclado" + sra.get ()); } // System de coleta de lixo.gc (); if (sra.get () == null) {System.out.println ("Um objeto entra no processo de coleta de lixo"); } else {System.out.println ("Um objeto ainda não foi reciclado" + sra.get ()); }}} classe A {} ## O resultado da saída é:
1 Um objeto não foi reciclado a@4807ccf62 Um objeto não foi reciclado a@4807ccf6
Quando a = nulo, o objeto A na memória da heap não terá mais referências fortes, mas há um objeto elegante referenciado por SRA apontando para o objeto A. Quando o método sra.get () é chamado pela primeira vez para retornar esse objeto indicador, uma vez que o coletor de lixo provavelmente ainda não realizou a coleta de lixo, get () tem resultado neste momento, o que é fácil de entender. Quando o programa executa o System.gc (); Forçando a coleta de lixo, através do sra.get (), verificou -se que o objeto indicado ainda pode ser obtido, indicando que o objeto A não foi coletado de lixo. Então, quando os objetos indicados pela referência suave começarão a ser coletados de lixo? As duas condições a seguir precisam ser atendidas:
1. Quando o objeto indica não tem nenhum objeto de referência forte apontando para ele;
2. Quando a máquina virtual tem memória insuficiente.
Portanto, a Softreference estende o tempo que indica que o objeto ocupa a memória da heap até que a máquina virtual tenha memória insuficiente. O coletor de lixo não recicla esse espaço de memória de heap.
3. Referência de Weak - Referência Fraca
Da mesma forma, a forma de uso geral de referência suave é a seguinte:
A a = novo a ();
FrawReference <a> WRA = nova fraca referência <a> (a);
Quando não há forte referência apontando para esse objeto, quais são suas características de coleta de lixo?
importar java.lang.ref.weakReference; public class referenceCetest {public static void main (string [] args) {a a = new a (); FrawReference <a> WRA = nova fraca referência <a> (a); a = nulo; if (wra.get () == null) {System.out.println ("Um objeto entra no processo de coleta de lixo"); } else {System.out.println ("Um objeto ainda não foi reciclado" + wra.get ()); } // System de coleta de lixo.gc (); if (wra.get () == null) {System.out.println ("Um objeto entra no processo de coleta de lixo"); } else {System.out.println ("Um objeto ainda não foi reciclado" + wra.get ()); }}} classe A {} ## O resultado da saída é:
Um objeto ainda não foi reciclado um objeto@52E5376AA entra no processo de coleta de lixo
A primeira saída do resultado é explicada como acima. Após a coleta de lixo, o wra.get () retornará nulo, indicando que indica que o objeto entrou no processo de coleta de lixo. Portanto, as características das citações fracas são resumidas como:
A referência fraca não altera o tempo de coleta de lixo do objeto de referência forte original. Uma vez indica que o objeto não possui nenhum objeto de referência forte, o objeto entra no processo normal de coleta de lixo.
Então, com base nessa característica, há uma pergunta: qual é o significado da referência fraca?
Seus principais cenários de uso são: atualmente existem referências fortes apontando para objetos de referência fortes. No momento, devido às necessidades de negócios, é necessário aumentar as referências a esse objeto e, ao mesmo tempo, não se destina a alterar o tempo de coleta de lixo dessa referência. Nesse momento, a frA -referência atende às necessidades e é comumente encontrada em alguns cenários com ciclos de vida.
A seguir, é apresentado um cenário para o uso da referência fraca no Android - combinando classes internas estáticas e referência fraca para resolver o possível problema de vazamento de memória do manipulador na atividade.
Na atividade, precisamos criar um novo thread para obter dados e usar o Método do manipulador - SendMessage. Aqui está o código geral para este processo:
classe pública MainActivity estende a atividade {// ... private Int Page; Manipulador privado Handler = new Handler () {@Override public void handleMessage (mensagem msg) {if (msg.what == 1) {// ... página ++; } outro { //... } }; }; @Override Protected void onCreate (pacote savedInstancestate) {super.oCreate (savedInstancestate); setContentView (r.layout.activity_main); // ... novo thread (novo runnable () {@Override public void run () {// .. message msg = message.obtain (); msg.what = 1; //msg.obj = xx; handler.sendMessage (msg);}}). start (); // ...}}Execute o link no eclispe, você verá uma mensagem de aviso: esta classe Handler deve ser estática ou vazamentos pode ocorrer ... Clique para visualizar essas informações, que descreve o problema nos detalhes e fornece uma solução sugestiva.
Problema: garante que as classes do manipulador não se mantenham em uma referência a um classídeo externo: HandlerLeaks, pois esse manipulador é declarado como uma classe interna, pode impedir que a classe externa seja coletada de lixo. Se o manipulador estiver usando um Looper ou MessageQueue para um thread que não seja o thread principal, não há problema. Se o manipulador estiver usando o looper ou o MessageQueue do encadeamento principal, você precisará consertar sua declaração de manipulador, da seguinte forma: Declare o manipulador como uma classe estática; na classe externa, instancie uma referência fraca à classe externa e passe esse objeto para o seu manipulador quando você instanciar o manipulador; Faça todas as referências aos membros da classe externa usando o objeto de referência fraca.
O significado geral é que é recomendável definir o manipulador como uma classe estática interna e definir uma referência à referência fraca nessa classe interna estática, devido a indicar o objeto de atividade externa.
Análise de problemas:
A atividade tem seu próprio ciclo de vida. Durante o processo de execução dos threads recém -abertos na atividade, o usuário pode pressionar a tecla traseira ou o sistema é uma memória insuficiente, etc. para reciclar essa atividade. Como os threads recém-lançados na atividade não seguirão o ciclo da própria atividade, ou seja, quando a atividade executa o OnDestroy, devido à existência de threads e HandleMessage do manipulador, o sistema originalmente espera realizar referências externas dessa atividade, que não pode ser implementado por uma classe interna não estática.
Portanto, ao usar o manipulador na atividade, por um lado, ele precisa ser definido como um formulário de classe interna estática, para que possa ser dissociado da classe externa e não reter mais referências à classe externa. Ao mesmo tempo, uma vez que a manutenção do manipulador geralmente precisa acessar ou modificar as propriedades da atividade; neste momento, a referência fraca apontando para essa atividade precisa ser definida dentro do manipulador para que ela não afete a recuperação da memória da atividade. Ao mesmo tempo, as propriedades da atividade podem ser acessadas em circunstâncias normais.
As recomendações oficiais do Google são:
classe pública MainActivity estende a atividade {// ... private Int Page; Privado MyHandler Mmyhandler = New Myhandler (isto); Classe estática privada MyHandler estende o manipulador {private fracos <MainActivity> wractivity; public MyHandler (Atividade da MainActivity) {this.Wractivity = new frAchereference <MainActivity> (atividade); } @Override public void handleMessage (mensagem msg) {if (wractivity.get () == null) {return; } MainActivity mActivity = wractivity.get (); if (msg.what == 1) {// ... mactivity.page ++; } else {// ...}}} @Override Void protegido OnCreate (pacote salvadonsista) {super.OnCreate (savedInstancestate); setContentView (r.layout.activity_main); // ... novo thread (new Runnable () {@Override public void run () {// .. message msg = message.obtain (); msg.what = 1; //msg.obj = xx; mmyhandler.sendMessage (msg);}}). start (); // ...}}Para softreferência e referência fraca, também existe uma referência de parâmetro construtora <T> e, quando o objeto indicado pela softreference ou fraco referência é de fato coletado de lixo, sua referência será colocada no referencequeue. Observe que, como acima, quando o método get () de Softreference ou Referência de Fraques retorna nulo, indica apenas que o objeto que indica que entrou no processo de coleta de lixo, e o objeto pode não ter sido coletado no lixo neste momento. Somente depois de confirmar que foi coletado de lixo, se for a referência, sua referência será colocada no ReferenceQueue.
Veja um exemplo abaixo:
public FrawReference <a> WRA = nova fraca referência <a> (a); a = nulo; if (wra.get () == null) {System.out.println ("Um objeto entra no processo de coleta de lixo"); } else {System.out.println ("Um objeto ainda não foi reciclado" + wra.get ()); } // System de coleta de lixo.gc (); if (wra.get () == null) {System.out.println ("Um objeto entra no processo de coleta de lixo"); } else {System.out.println ("Um objeto ainda não foi reciclado" + wra.get ()); }}} classe A {@Override Protected void finalize () lança Throwable {super.finalize (); System.out.println ("em uma finalização"); }} ## O resultado da saída é:
1 Um objeto não foi reciclado a@46993AAA2 Um objeto foi reciclado 3 em uma finalização
Isso também verifica a declaração "entrando no processo de coleta de lixo" mencionada acima. Vejamos um pedaço de código em combinação com a ReferenceQueue:
public ReferenceQueue <a> rq = new ReferenceQueue <a> (); FrawReference <a> wra = new fratingReference <a> (a, rq); a = nulo; if (wra.get () == null) {System.out.println ("Um objeto entra no processo de coleta de lixo"); } else {System.out.println ("Um objeto ainda não foi reciclado" + wra.get ()); } System.out.println ("rq item:" + rq.poll ()); // Sistema de coleta de lixo.gc (); if (wra.get () == null) {System.out.println ("Um objeto entra no processo de coleta de lixo"); } else {System.out.println ("Um objeto ainda não foi reciclado" + wra.get ()); } /* tente {thread.sleep (1000); } catch (interruptedException e) {e.printStackTrace (); } */ System.out.println ("rq item:" + rq.poll ()); }} classe A {@Override Protected void finalize () lança o Throwable {super.finalize (); System.out.println ("em uma finalização"); }} ## O resultado da saída é:
Um objeto ainda não foi reciclado um item@302B2C81RQ: Nulla Object entra no processo de coleta de lixo RQ Item: Nullin a finalize
Assim, é verificado que "referências de softreferência ou referência fraca que entram apenas o processo de coleta de lixo não foram adicionadas ao ReferenceQueue".
public ReferenceQueue <a> rq = new ReferenceQueue <a> (); FrawReference <a> wra = new fratingReference <a> (a, rq); a = nulo; if (wra.get () == null) {System.out.println ("Um objeto entra no processo de coleta de lixo"); } else {System.out.println ("Um objeto ainda não foi reciclado" + wra.get ()); } System.out.println ("rq item:" + rq.poll ()); // Sistema de coleta de lixo.gc (); if (wra.get () == null) {System.out.println ("Um objeto entra no processo de coleta de lixo"); } else {System.out.println ("Um objeto ainda não foi reciclado" + wra.get ()); } tente {thread.sleep (1); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("rq item:" + rq.poll ()); }} classe A {@Override Protected void finalize () lança o Throwable {super.finalize (); System.out.println ("em uma finalização"); }} ## O resultado da saída é:
Um objeto ainda não foi reciclado um item@6276E1DBRQ: o objeto Nulla entra no processo de coleta de lixo em um item Finalizerq: java.lang.ref.weakreference@645064f
Isso confirma a declaração acima.
4.Phantomreference
Comparado com a softreferência ou a referência fraca, as principais diferenças na referência fantasma são refletidas nos seguintes pontos:
1. Phantomreference possui apenas uma formação fantasma do construtor (referência t, referência para cenário <? Super t> q), portanto, o fantasma deve ser usado em combinação com o referencequeue;
2. Independentemente de haver uma forte referência ao objeto indicador, apontando para a fantasma, o método get () de fantomreferença retorna o resultado nulo.
public ReferenceQueue <a> rq = new ReferenceQueue <a> (); Phantomreference <a> PRA = new Phantomreference <a> (A, RQ); System.out.println ("Pra.get ():" + Pra.get ()); a = nulo; System.gc (); tente {thread.sleep (1); } catch (interruptedException e) {e.printStackTrace (); } System.out.println ("rq item:" + rq.poll ()); }} classe A {} ## O resultado da saída é:
Pra.get (): nullrq Item: java.lang.ref.phantomreference@1da12fc0
O thread.sleep (1); No código, funciona o mesmo que no exemplo acima, e ambos garantem que o thread de coleta de lixo possa ser executado. Caso contrário, as referências virtuais ao objeto indicador que entram no processo de coleta de lixo sem serem realmente coletadas de lixo não serão adicionadas à phantomreferência.
Como a referência fraca, o fantasma não altera o tempo de coleta de lixo de seu objeto indicador. Pode -se concluir que a função do ReferenceQueue é usada principalmente para ouvir a Softreference/fracos -referência/phantomreference indicando se o objeto foi coletado de lixo.
O exposto acima é o conteúdo completo da análise abrangente dos tipos de referência Java/Android e uso trazido a você pelo editor. Espero que seja útil para você e apoiar mais wulin.com ~