Il existe quatre types de référence dans Java / Android, à savoir:
Référence forte - Référence forte
Référence douce - Référence douce
Référence faible - Référence faible
Référence fantôme - citation virtuelle
Différents types de référence ont des caractéristiques différentes et correspondent également à différents scénarios d'utilisation.
1. Référence forte - Référence forte
Le type de référence le plus courant dans le codage réel. Des formes communes telles que: a a = new a (); etc. La forte référence elle-même est stockée dans la mémoire de la pile, et il stocke l'adresse à l'objet en mémoire. Généralement, lorsqu'il n'y a plus de forte référence à l'objet en mémoire le pointant, la machine de collecte des ordures commence à considérer la collection de déchets qui pourrait être effectuée sur cette mémoire. Si le codage: a = null, pour le moment, l'adresse qui a été allouée dans le tas et créée n'a pas d'autres références. Lorsque le système effectue une collecte de déchets, la mémoire du tas sera collectée aux ordures.
Softreference, FaibleRreference et Phantomreference sont toutes des sous-classes de la classe java.lang.ref.reference. La référence, en tant que classe de base abstraite, définit les opérations de base de ses objets sous-classe. Les sous-classes de référence ont toutes les caractéristiques suivantes:
1. La sous-classe de référence ne peut pas être créée directement sans paramétrage. Il doit au moins utiliser l'objet de référence fort comme paramètre de construction pour créer leurs objets sous-classe respectifs;
2. Étant donné que l'objet est créé dans 1 avec l'objet de référence solide comme paramètre de construction, les objets de la mémoire du tas pointés par la référence à l'origine ne seront plus directement liés à la référence forte elle-même, mais auront également une certaine connexion avec la référence de l'objet de référence de sous-classe. Et cette connexion peut affecter la collecte des ordures de l'objet.
Selon les différentes caractéristiques d'influence de différents objets de sous-classe sur la collecte des ordures de leurs objets indicateurs (de fortes références à des objets dans la mémoire du tas pointés), trois sous-classes sont formées, à savoir la perférence, la faible référence et la phantomréférence.
2. RÉFÉRENCE DE SOFT - Référence douce
La forme d'utilisation générale de la référence douce est la suivante:
A a = nouveau a ();
Softreference <a> SRA = nouvelle softreference <a> (a);
Grâce à la forte référence de l'objet en tant que paramètre, un objet Softreference est créé et le WRA dans la mémoire de pile pointe vers cet objet.
À l'heure actuelle, le codage suivant est effectué: a = null. Quel impact a-t-il sur la collecte des ordures de l'objet à initialement indiqué par un?
Jetons un coup d'œil aux résultats de sortie du programme suivant:
Importer java.lang.ref.softreference; public class ReferenceTest {public static void main (String [] args) {a a = new a (); Softreference <a> SRA = nouvelle softreference <a> (a); a = null; if (sra.get () == null) {System.out.println ("Un objet entre dans le processus de collecte des ordures"); } else {System.out.println ("Un objet n'a pas encore été recyclé" + sra.get ()); } // Garbage Collection System.gc (); if (sra.get () == null) {System.out.println ("Un objet entre dans le processus de collecte des ordures"); } else {System.out.println ("Un objet n'a pas encore été recyclé" + sra.get ()); }}} classe A {} ## Le résultat de la sortie est:
1 Un objet n'a pas été recyclé A @ 4807ccf62 Un objet n'a pas été recyclé A @ 4807ccf6
Lorsque A = NULL, l'objet A dans la mémoire du tas n'aura plus de références fortes, mais il y a un objet à la mode référencé par SRA pointant vers l'objet A. Lorsque la méthode sra.get () est appelée pour la première fois pour retourner cet objet indicateur, car le collecteur de déchets n'a probablement pas encore effectué la collecte des ordures, get () a un résultat pour le moment, ce qui est facile à comprendre. Lorsque le programme exécute System.gc (); Forçant la collecte des ordures, via sra.get (), il est constaté que l'objet indiqué peut encore être obtenu, indiquant que l'objet A n'a pas été collecté à la poubelle. Ainsi, quand les objets indiqués par la référence douce commencent-ils à être collectés des ordures? Les deux conditions suivantes doivent être remplies:
1. Lorsque l'objet, il indique n'a pas d'objet de référence solide qui le pointe;
2. Lorsque la machine virtuelle a une mémoire insuffisante.
Par conséquent, Softreference prolonge le temps qu'il indique que l'objet occupe la mémoire du tas jusqu'à ce que la machine virtuelle ait une mémoire insuffisante. Le collecteur des ordures ne recycle pas cet espace mémoire de tas.
3. Référence à la vapeur - Référence faible
De même, la forme d'utilisation générale de la référence douce est la suivante:
A a = nouveau a ();
FaibleReference <a> WRA = NOUVEAU FAILERFELER <A> (A);
Lorsqu'il n'y a pas de référence forte pointant vers cet objet, quelles sont ses caractéristiques de collecte des ordures?
import java.lang.ref.weakReference; public class ReferenceTest {public static void main (String [] args) {a a = new a (); FaibleReference <a> WRA = NOUVEAU FAILERFELER <A> (A); a = null; if (wra.get () == null) {System.out.println ("Un objet entre dans le processus de collecte des ordures"); } else {System.out.println ("Un objet n'a pas encore été recyclé" + wra.get ()); } // Garbage Collection System.gc (); if (wra.get () == null) {System.out.println ("Un objet entre dans le processus de collecte des ordures"); } else {System.out.println ("Un objet n'a pas encore été recyclé" + wra.get ()); }}} classe A {} ## Le résultat de la sortie est:
Un objet n'a pas encore été recyclé, un objet @ 52E5376AA entre dans le processus de collecte des ordures
La première sortie du résultat est expliquée comme ci-dessus. Après la collecte des ordures, Wra.get () reviendra NULL, indiquant qu'il indique que l'objet est entré dans le processus de collecte des ordures. Par conséquent, les caractéristiques des citations faibles sont résumées comme suit:
LowerReference ne change pas le calendrier de collecte des ordures de l'objet de référence fort d'origine. Une fois qu'il indique que l'objet n'a pas d'objet de référence solide, l'objet entre dans le processus de collecte normal des ordures.
Donc, sur la base de cette caractéristique, il y a une question: quelle est la signification de la référence faible?
Ses principaux scénarios d'utilisation sont: il existe actuellement de fortes références pointant vers des objets de référence solides. Pour le moment, en raison des besoins commerciaux, il est nécessaire d'augmenter les références à cet objet, et en même temps, il n'est pas destiné à modifier le calendrier de collecte des ordures de cette référence. À l'heure actuelle, la référence faible répond simplement aux besoins et se trouve couramment dans certains scénarios avec des cycles de vie.
Ce qui suit est un scénario d'utilisation de la référence faible dans Android - combinant des classes internes statiques et des références faibles pour résoudre le problème de fuite de mémoire du gestionnaire possible dans l'activité.
Dans l'activité, nous devons créer un nouveau thread pour obtenir des données et utiliser le gestionnaire - méthode SendMessage. Voici le code général de ce processus:
La classe publique MainActivity étend l'activité {// ... Private int page; Handler Private Handler = new Handler () {@Override public void handleMessage (message msg) {if (msg.what == 1) {// ... page ++; } autre { //... } }; }; @Override Protected void onCreate (bundle SavedInStanceState) {super.onCreate (SavedInStanceState); setContentView (r.layout.activity_main); // ... nouveau thread (new Runnable () {@Override public void run () {// .. message msg = message.obtain (); msg.what = 1; //msg.obj = xx; handler.sendMessage (msg);}}). start (); // ...}}Exécutez le lien dans EclinSpe, vous verrez un message d'avertissement: cette classe de gestionnaire doit être statique ou des fuites peuvent se produire ... cliquez pour afficher ces informations, qui décrit le problème dans les détails et fournit une solution suggestive.
Problème: garantit que les classes de gestionnaires ne tiennent pas à une référence à un classique extérieur: HandlerLeakSince, ce gestionnaire est déclaré comme une classe intérieure, il peut empêcher la classe extérieure d'être collectée à la poubelle. Si le gestionnaire utilise un LOOPER ou MessageQueue pour un thread autre que le thread principal, il n'y a pas de problème. Si le gestionnaire utilise le looper ou le message du fil principal, vous devez réparer votre déclaration de gestionnaire, comme suit: Déclarez le gestionnaire comme une classe statique; dans la classe extérieure, instanciez une référence faible à la classe extérieure et passez cet objet à votre gestionnaire lorsque vous instanciez le manageur; Faites toutes les références aux membres de la classe extérieure à l'aide de l'objet FaibleRreference.
La signification générale est qu'il est recommandé de définir le gestionnaire comme une classe statique interne et de définir une référence à la référence faible dans cette classe interne statique, en raison de l'indication de l'objet d'activité externe.
Analyse des problèmes:
L'activité a son propre cycle de vie. Pendant le processus en cours d'exécution des threads nouvellement ouverts dans l'activité, l'utilisateur peut appuyer sur la touche arrière ou le système est une mémoire insuffisante, etc. pour recycler cette activité. Étant donné que les fils nouvellement lancés dans l'activité ne suivront pas le cycle de l'activité elle-même, c'est-à-dire lorsque l'activité exécute OnDestroy, en raison de l'existence de threads et de Handlessage du Handler, le système espère à l'origine à effectuer des références de mémoire de cette activité, car les problèmes de réticulation de la mémoire non statiques, résultant dans des problèmes de maîtrise de mémoire possibles.
Par conséquent, lors de l'utilisation du gestionnaire dans l'activité, d'une part, il doit être défini comme une forme de classe interne statique, de sorte qu'il peut être découplé à partir de la classe externe et ne maintient plus de références à la classe externe. Dans le même temps, puisque le maintien du maintien dans le gestionnaire doit généralement accéder ou modifier les propriétés de l'activité, pour le moment, la référence faible pointant vers cette activité doit être définie à l'intérieur du gestionnaire afin qu'elle n'affecte pas la récupération de la mémoire de l'activité. Dans le même temps, les propriétés de l'activité sont accessibles dans des circonstances normales.
Les recommandations officielles de Google sont:
La classe publique MainActivity étend l'activité {// ... Private int page; MyHandler privé mmyHandler = new MyHandler (this); classe statique privée MyHandler étend le gestionnaire {private faibleReference <MainActivity> Wractivity; public myHandler (MainActivity Activity) {this.wractivity = new FaibleReference <MainActivity> (activité); } @Override public void handleMessage (message msg) {if (wractivity.get () == null) {return; } MACTIVITÉ MAINACTIVITY = Wractivity.get (); if (msg.what == 1) {// ... mActivity.Page ++; } else {// ...}}} @Override Protected void onCreate (bundle SavedInStanceState) {super.onCreate (SavedInStanceState); setContentView (r.layout.activity_main); // ... nouveau thread (new Runnable () {@Override public void run () {// .. message msg = message.obtain (); msg.what = 1; //msg.obj = xx; mmyhandler.sendMessage (msg);}}). start (); // ...}}Pour la conférence de softre et de faiblesse, il existe également un paramètre de constructeur référence à la référence <t>, et lorsque l'objet indiqué par la référence ou la référence faible est en effet collecté, sa référence sera placée dans la référence. Notez que comme ci-dessus, lorsque la méthode GET () de Softreference ou de FaibleReference renvoie NULL, elle indique seulement que l'objet qu'il indique est entré dans le processus de collecte des ordures, et l'objet n'a peut-être pas été collecté à l'heure à ce moment. Ce n'est qu'après avoir confirmé qu'il a été collecté par les ordures, si la référence est, sa référence sera placée dans la référence.
Voir un exemple ci-dessous:
classe publique référentieltest {public static void main (String [] args) {a a = new a (); FaibleReference <a> WRA = NOUVEAU FAILERFELER <A> (A); a = null; if (wra.get () == null) {System.out.println ("Un objet entre dans le processus de collecte des ordures"); } else {System.out.println ("Un objet n'a pas encore été recyclé" + wra.get ()); } // Garbage Collection System.gc (); if (wra.get () == null) {System.out.println ("Un objet entre dans le processus de collecte des ordures"); } else {System.out.println ("Un objet n'a pas encore été recyclé" + wra.get ()); }}} classe A {@Override Protected void finalize () lève lanceable {super.Finalize (); System.out.println ("Dans une finalisation"); }} ## Le résultat de la sortie est:
1 Un objet n'a pas été recyclé A @ 46993AAA2 Un objet a été recyclé 3 dans une finalisation
Cela vérifie également l'énoncé "entrant dans le processus de collecte des ordures" mentionné ci-dessus. Regardons un morceau de code en combinaison avec ReferenceQueue:
classe publique référentieltest {public static void main (String [] args) {a a = new a (); ReferenceQueue <a> rq = new Referenceeue <a> (); FaibleReference <a> WRA = Nouvelle faible référence <a> (A, RQ); a = null; if (wra.get () == null) {System.out.println ("Un objet entre dans le processus de collecte des ordures"); } else {System.out.println ("Un objet n'a pas encore été recyclé" + wra.get ()); } System.out.println ("RQ ITEM:" + rq.poll ()); // Système de collecte des ordures.gc (); if (wra.get () == null) {System.out.println ("Un objet entre dans le processus de collecte des ordures"); } else {System.out.println ("Un objet n'a pas encore été recyclé" + wra.get ()); } / * try {Thread.Sleep (1000); } catch (InterruptedException e) {e.printStackTrace (); } * / System.out.println ("RQ ITEM:" + rq.poll ()); }} classe A {@Override Protected void finalize () lève lanceable {super.Finalize (); System.out.println ("Dans une finalisation"); }} ## Le résultat de la sortie est:
Un objet n'a pas encore été recyclé un @ 302B2C81RQ Article: l'objet Nulla entre dans le processus de collecte des ordures RQ Article: Nullin A Finalise
Ainsi, il est vérifié que "les références de référence de Softreference ou FaibleRreference qui entrent uniquement sur le processus de collecte des ordures n'ont pas été ajoutées à la référence".
classe publique référentieltest {public static void main (String [] args) {a a = new a (); ReferenceQueue <a> rq = new Referenceeue <a> (); FaibleReference <a> WRA = Nouvelle faible référence <a> (A, RQ); a = null; if (wra.get () == null) {System.out.println ("Un objet entre dans le processus de collecte des ordures"); } else {System.out.println ("Un objet n'a pas encore été recyclé" + wra.get ()); } System.out.println ("RQ ITEM:" + rq.poll ()); // Système de collecte des ordures.gc (); if (wra.get () == null) {System.out.println ("Un objet entre dans le processus de collecte des ordures"); } else {System.out.println ("Un objet n'a pas encore été recyclé" + wra.get ()); } essayez {Thread.Sleep (1); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("RQ ITEM:" + rq.poll ()); }} classe A {@Override Protected void finalize () lève lanceable {super.Finalize (); System.out.println ("Dans une finalisation"); }} ## Le résultat de la sortie est:
Un objet n'a pas encore été recyclé un @ 6276E1DBRQ Article: l'objet Nulla entre dans le processus de collecte des ordures dans un élément Finalizerq: java.lang.ref.weakreference@645064f
Cela confirme la déclaration ci-dessus.
4.Phantomreference
Par rapport à la conférence de moussie ou à la faiblesse, les principales différences de fantomréférence se reflètent dans les points suivants:
1. Phantomreference n'a qu'un seul Phantomreference du constructeur (référence t, ReferenceQueue <? Super T> Q), donc la phantomréférence doit être utilisée en combinaison avec ReferenceQueue;
2. Peu importe qu'il y ait une forte référence à l'objet indicateur pointant vers la fantôme, la méthode Get () de Phantomreference renvoie le résultat nul.
classe publique référentieltest {public static void main (String [] args) {a a = new a (); ReferenceQueue <a> rq = new Referenceeue <a> (); Phantomreference <a> PRA = Nouvelle Phantomreference <a> (A, RQ); System.out.println ("pra.get ():" + pra.get ()); a = null; System.gc (); essayez {thread.sleep (1); } catch (InterruptedException e) {e.printStackTrace (); } System.out.println ("RQ ITEM:" + rq.poll ()); }} classe A {} ## Le résultat de la sortie est:
pra.get (): Nullrq Article: java.lang.ref.phantomreference@1da12fc0
Le fil.Sleep (1); dans le code fonctionne comme dans l'exemple ci-dessus, et les deux garantissent que le thread de collecte des ordures peut s'exécuter. Sinon, des références virtuelles à l'objet indicateur qui entrent dans le processus de collecte des ordures sans être réellement collectée ne seront pas ajoutées à la fantôme.
Comme la référence faible, la phantomréférence ne change pas le calendrier de collecte des ordures de son objet indiquant. On peut conclure que la fonction de ReferenceQueue est principalement utilisée pour écouter le softreference / faible référence / phantomréférence indiquant si l'objet a été collecté par les déchets.
Ce qui précède est le contenu complet de l'analyse complète des types de référence Java / Android et de l'utilisation que vous avez été que l'éditeur. J'espère que cela vous sera utile et soutenir Wulin.com plus ~