Es gibt vier Referenztypen in Java/Android, nämlich:
Starke Referenz - starke Referenz
Weiche Referenz - Weiche Referenz
Schwache Referenz - Schwache Referenz
Phantomreferenz - Virtuelles Zitat
Unterschiedliche Referenztypen haben unterschiedliche Eigenschaften und entsprechen auch unterschiedlichen Nutzungsszenarien.
1. Strong Referenz - starke Referenz
Die häufigste Art der Referenz in der tatsächlichen Codierung. Gemeinsame Formen wie: a = neu a (); usw. Die starke Referenz selbst wird im Stapelspeicher gespeichert und speichert die Adresse in das Objekt im Speicher. Im Allgemeinen beginnt die Garbage Collection -Maschine, wenn es keinen starken Hinweis auf das Objekt im Speicher gibt, der in diesem Speicher möglicherweise die Müllsammlung berücksichtigt. Wenn Codierung: a = null, enthält die Adresse, die gerade im Haufen und erstellt wurde, keine anderen Referenzen. Wenn das System Müllsammlung ausführt, wird der Heap -Speicher Müll gesammelt.
Sozidreferenz, Schwache und Phantomreferenz sind alle Unterklassen der Klasse java.lang.ref.Reference. Die Referenz definiert als abstrakte Basisklasse die grundlegenden Operationen seiner Subklassenobjekte. Referenzunterklassen haben alle die folgenden Eigenschaften:
1. Die Referenzunterklasse kann nicht ohne Parametrisierung direkt erstellt werden. Es muss zumindest das starke Referenzobjekt als Konstruktionsparameter verwenden, um ihre jeweiligen Subklassenobjekte zu erstellen.
2. Da das Objekt in 1 mit dem starken Referenzobjekt als Konstruktionsparameter erstellt wird, werden die Objekte im Heap -Speicher, auf die durch die ursprünglich starke Referenz hingewiesen wird, nicht mehr direkt mit der starken Referenz selbst zusammenhängen, sondern auch eine bestimmte Verbindung mit der Referenz des Referenzobjekts von Subklassen. Und diese Verbindung kann die Müllsammlung des Objekts beeinflussen.
Gemäß den verschiedenen Einflussmerkmalen verschiedener Subklassenobjekte zur Müllsammlung ihrer Indikatorobjekte (starke Verweise auf Objekte im Heap -Speicher) werden drei Unterklassen gebildet, nämlich Weiche, Schwachreferenz und Phantomreferenz.
2. Soft Reference - Soft Reference
Die allgemeine Verwendung der weichen Referenz lautet wie folgt:
A a = neu a ();
Softreferenz <a> SRA = New Softrreference <a> (a);
Durch die starke Referenz des Objekts als Parameter wird ein Softreferenzobjekt erstellt und der WRA im Stapelspeicher auf dieses Objekt zeigt.
Zu diesem Zeitpunkt wird die folgende Codierung durchgeführt: a = null. Welchen Einfluss hat es auf die Müllsammlung des Objekts, auf das ein ursprünglich von A gezeigt wurde?
Schauen wir uns die Ausgabeergebnisse des folgenden Programms an:
importieren java.lang.ref.softreference; public class Referencetest {public static void main (String [] args) {a = new a (); Softreferenz <a> SRA = New Softrreference <a> (a); a = null; if (sra.get () == null) {System.out.println ("Ein Objekt tritt in den Müllsammlungsprozess"); } else {System.out.println ("Ein Objekt wurde noch nicht recycelt" + sra.get ()); } // Garbage Collection System.gc (); if (sra.get () == null) {System.out.println ("Ein Objekt tritt in den Müllsammlungsprozess"); } else {System.out.println ("Ein Objekt wurde noch nicht recycelt" + sra.get ()); }}} Klasse A {} ## Das Ausgabeergebnis ist:
1 Ein Objekt wurde nicht recycelt. 4807CCF62 Ein Objekt wurde nicht auf@4807CCF6 recycelt.
Wenn a = null ist, gibt das A -Objekt im Heap -Speicher keine starken Verweise mehr darauf, aber es gibt ein modisches Objekt, auf das SRA auf das A -Objekt hinweist. Wenn die SRA.get () -Methode zum ersten Mal aufgerufen wird, um dieses Indikatorobjekt zurückzugeben, hat Get () zu diesem Zeitpunkt ein Ergebnis, was leicht zu verstehen ist, da der Müllsammler wahrscheinlich noch keine Müllsammlung durchgeführt hat. Wenn das Programm system.gc () ausführt; Durch Sra.get () wird die Müllsammlung erzwingen, dass das angegebene ein Objekt noch erhalten werden kann, was darauf hinweist, dass das A -Objekt nicht Müll gesammelt wurde. Wann werden die von der weiche Referenz angegebenen Objekte in Müll gesammelt? Die folgenden zwei Bedingungen müssen erfüllt sein:
1. Wenn das von ihm angezeigte Objekt kein starkes Referenzobjekt hat, das darauf hinweist;
2. Wenn die virtuelle Maschine nicht genügend Speicher hat.
Daher erweitert Softrreference die Zeit, die es angibt, dass das Objekt den Heap -Speicher einnimmt, bis die virtuelle Maschine nicht genügend Speicher hat. Der Müllkollektor recycelt diesen Heap -Speicherraum nicht.
3. Weak Referenz - Schwache Referenz
In ähnlicher Weise lautet die allgemeine Verwendung von Soft Reference wie folgt:
A a = neu a ();
WeaPreference <a> WRA = New Wecreference <a> (a);
Wenn es keine starke Referenz gibt, die auf dieses Objekt hinweist, welche Eigenschaften sind die Müllsammlungsmerkmale?
importieren java.lang.ref.WeakReferation; öffentliche Klasse Referencetest {public static void main (String [] args) {a a = new a (); WeaPreference <a> WRA = New Wecreference <a> (a); a = null; if (wra.get () == null) {System.out.println ("Ein Objekt betritt den Müllsammlungsprozess"); } else {System.out.println ("Ein Objekt wurde noch nicht recycelt" + wra.get ()); } // Garbage Collection System.gc (); if (wra.get () == null) {System.out.println ("Ein Objekt tritt in den Müllsammlungsprozess"); } else {System.out.println ("Ein Objekt wurde noch nicht recycelt" + wra.get ()); }}} Klasse A {} ## Das Ausgabeergebnis ist:
Ein Objekt wurde noch nicht recycelt, ein@52E5376AA -Objekt tritt in den Müllsammlungsprozess ein
Die erste Ergebnisausgabe wird wie oben erläutert. Nach der Müllsammlung wird Wra.get () NULL zurückgeben, was darauf hinweist, dass das Objekt in den Müllsammlungsprozess eingegeben wurde. Daher werden die Eigenschaften schwacher Zitate zusammengefasst als:
Weepreference ändert den Müllsammlungszeitpunkt des ursprünglichen starken Referenzobjekts nicht. Sobald es angibt, dass das Objekt kein starkes Referenzobjekt hat, tritt das Objekt in den normalen Müllsammlungsprozess ein.
Basierend auf dieser Eigenschaft gibt es also eine Frage: Welche Bedeutung hat Schwachreferenz?
Seine Hauptnutzungsszenarien sind: Derzeit gibt es starke Referenzen auf starke Referenzobjekte. Zu diesem Zeitpunkt ist es aufgrund der geschäftlichen Bedürfnisse erforderlich, die Verweise auf dieses Objekt zu erhöhen, und gleichzeitig ist es nicht beabsichtigt, den Zeitpunkt der Müllsammlung dieser Referenz zu ändern. Zu diesem Zeitpunkt erfüllt WeaPreference nur die Bedürfnisse und kommt in einigen Szenarien mit Lebenszyklen häufig vor.
Das Folgende ist ein Szenario für die Verwendung von Wecreference in Android - kombiniert statische innere Klassen und Schwachreferenz, um das mögliche Handler -Speicher -Leck -Problem in der Aktivität zu lösen.
In der Aktivität müssen wir einen neuen Thread erstellen, um Daten zu erhalten und Handler -SendMessage -Methode zu verwenden. Hier ist der allgemeine Code für diesen Prozess:
MainActivity der öffentlichen Klasse erweitert die Aktivität {// ... private int page; private Handler Handler = new Handler () {@Override public void Handlemessage (Message MSG) {if (msg.what == 1) {// ... Seite ++; } anders { //... } }; }; @Override Protected void OnCreate (Bündel SavedInstancestate) {Super.oncreate (SavedInstancestate); setContentView (r.layout.Activity_main); // ... neuer Thread (neuer Runnable () {@Override public void run () {// .. message msg = message.obtain (); msg.what = 1; //msg.obj = xx; Handler.SendMessage (msg);}}). // ...}}Ausführen von Link in EcLispe sehen Sie eine Warnmeldung: Diese Handler -Klasse sollte statisch sein, oder Lecks können auftreten ... Klicken Sie auf diese Informationen, die das Problem in den Details beschreiben und eine suggestive Lösung bieten.
Ausgabe: Stellen Sie sicher, dass Handlerklassen nicht an einem Verweis auf eine äußere Klassiker festhalten: HandlerleakSince Dieser Handler wird als innere Klasse deklariert. Sie kann verhindern, dass die äußere Klasse Müll gesammelt wird. Wenn der Handler einen Looper oder Messagequeue für einen anderen Thread als den Hauptfaden verwendet, gibt es kein Problem. Wenn der Handler die Looper oder Messagequeue des Hauptfadens verwendet, müssen Sie Ihre Handler -Erklärung wie folgt reparieren: Deklarieren Sie den Handler als statische Klasse; In der äußeren Klasse können Sie eine schwache Renferenz für die äußere Klasse instanziieren und dieses Objekt an Ihren Handler weitergeben, wenn Sie den Handler instanziieren. Machen Sie alle Verweise auf Mitglieder der äußeren Klasse mit dem WeaCreference -Objekt.
Die allgemeine Bedeutung ist, dass es empfohlen wird, den Handler als interne statische Klasse zu definieren und einen Hinweis auf Schwachreferenz in dieser statischen inneren Klasse zu definieren, da das externe Aktivitätsobjekt angegeben ist.
Problemanalyse:
Aktivität hat ihren eigenen Lebenszyklus. Während des laufenden Prozesses neu geöffneter Threads in der Aktivität kann der Benutzer die Rücktaste drücken, oder das System ist nicht genügend Speicher usw., um diese Aktivität zu recyceln. Da die neu gestarteten Themen in der Aktivität nicht dem Zyklus der Aktivität selbst folgen, dh wenn die Aktivität Ondestroy ausführt, hofft das System aufgrund der Existenz von Threads und Handlers Handlemessage ursprünglich, die Wiederherstellung dieser Aktivität von Speicher auszuführen, die diese Aktivität nicht implementiert, da die nicht statischen internen Klassen implizit Referenzen auf externe Klassen implizit anhand von externen Klassen, die sich mit externer Klassen entspannen, in der Lage sind, sich zu entspannen und sich auf die Erkenntnis zu entspannen.
Bei der Verwendung von Handler in Aktivität muss es daher einerseits als statische Innenklassenform definiert werden, damit sie von der externen Klasse entkoppelt werden und keine Verweise mehr auf die externe Klasse enthalten kann. Gleichzeitig muss die Eigenschaften der Aktivität im Allgemeinen auf die Eigenschaften der Aktivität zugreifen oder diese ändern müssen. Zu diesem Zeitpunkt muss die auf diese Aktivität angezeigte Schwachreferenz im Handler definiert werden, damit er die Speicherwiederherstellung der Aktivität nicht beeinträchtigt. Gleichzeitig können unter normalen Umständen auf die Eigenschaften der Aktivität zugegriffen werden.
Die offiziellen Google -Empfehlungen sind:
MainActivity der öffentlichen Klasse erweitert die Aktivität {// ... private int page; privat myhandler mmyHandler = new myHandler (this); Private statische Klasse MyHandler erweitert den Handler {private Weepreference <Anaktivität> Wraktivität; public MyHandler (MainActivity -Aktivität) {this.wractivity = new waceReference <MainActivity> (Aktivität); } @Override public void Handlemessage (Message MSG) {if (Wractivity.get () == null) {return; } MainActivity -Maktivität = Wraktivität.get (); if (msg.what == 1) {// ... macctivity.page ++; } else {// ...}}} @Override Protected void OnCreate (Bündel savedInstancestate) {Super.oncreate (SavedInstancestate); setContentView (r.layout.Activity_main); // ... neuer Thread (neuer Runnable () {@Override public void run () {// .. message msg = message.obtain (); msg.what = 1; //msg.obj = xx; // ...}}Für Weiche und Schwachreferenz gibt es auch einen Konstruktorparameterreferenzqueue <t>, und wenn das durch Weichweite oder Schwachreferenz angezeigte Objekt tatsächlich Müll gesammelt wird, wird seine Referenz in das Referenzqueue platziert. Beachten Sie, dass wie oben die Get () -Methode der Sozidreferenz oder Schwachempfänger NULL zurückgibt, nur angibt, dass das von ihm angegebene Objekt in den Müllsammlungsprozess eingegeben wurde und das Objekt derzeit möglicherweise nicht Müll gesammelt wurde. Erst nachdem bestätigt wurde, dass es Müll gesammelt hat, wird seine Referenz in der Referenzqueue platziert.
Siehe ein Beispiel unten:
öffentliche Klasse Referencetest {public static void main (String [] args) {a = new a (); WeaPreference <a> WRA = New Wecreference <a> (a); a = null; if (wra.get () == null) {System.out.println ("Ein Objekt betritt den Müllsammlungsprozess"); } else {System.out.println ("Ein Objekt wurde noch nicht recycelt" + wra.get ()); } // Garbage Collection System.gc (); if (wra.get () == null) {System.out.println ("Ein Objekt betritt den Müllsammlungsprozess"); } else {System.out.println ("Ein Objekt wurde noch nicht recycelt" + wra.get ()); }}} Klasse A {@Override Protected void endfinalize () löscht Throwable {Super.finalize (); System.out.println ("in einem Finalize"); }} ## Das Ausgabeergebnis ist:
1 Ein Objekt wurde nicht mit 46993aaa2 recycelt. In einem Finalize wurde ein Objekt 3 recycelt.
Dies überprüft auch die oben erwähnte Aussage "Eingabe des Müllsammlungsprozesses". Schauen wir uns einen Code in Kombination mit Referenzqueue an:
öffentliche Klasse Referencetest {public static void main (String [] args) {a = new a (); Referenzqueue <a> rq = new referencequeue <a> (); WeaCreference <a> WRA = new Wecreference <a> (a, rq); a = null; if (wra.get () == null) {System.out.println ("Ein Objekt betritt den Müllsammlungsprozess"); } else {System.out.println ("Ein Objekt wurde noch nicht recycelt" + wra.get ()); } System.out.println ("RQ item:" + rq.poll ()); // Garbage Collection System.gc (); if (wra.get () == null) {System.out.println ("Ein Objekt betritt den Müllsammlungsprozess"); } else {System.out.println ("Ein Objekt wurde noch nicht recycelt" + wra.get ()); } /* try {thread.sleep (1000); } catch (interruptedException e) {e.printstacktrace (); } */ System.out.println ("RQ item:" + rq.poll ()); }} Klasse A {@Override Protected void endfinalize () löscht Throwable {Super.Finalize (); System.out.println ("in einem Finalize"); }} ## Das Ausgabeergebnis ist:
Ein Objekt wurde noch nicht recycelt. Ein@302B2C81RQ -Element: Nulla -Objekt tritt in den Müllsammlungsprozess RQ -Element: Nullin A Finalize ein
Somit wird verifiziert, dass "Weiche oder Schwache, die nur in den Referenzprozess hinzugefügt wurden".
öffentliche Klasse Referencetest {public static void main (String [] args) {a = new a (); Referenzqueue <a> rq = new referencequeue <a> (); WeaCreference <a> WRA = new Wecreference <a> (a, rq); a = null; if (wra.get () == null) {System.out.println ("Ein Objekt betritt den Müllsammlungsprozess"); } else {System.out.println ("Ein Objekt wurde noch nicht recycelt" + wra.get ()); } System.out.println ("RQ item:" + rq.poll ()); // Garbage Collection System.gc (); if (wra.get () == null) {System.out.println ("Ein Objekt betritt den Müllsammlungsprozess"); } else {System.out.println ("Ein Objekt wurde noch nicht recycelt" + wra.get ()); } try {thread.sleep (1); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("RQ item:" + rq.poll ()); }} Klasse A {@Override Protected void endfinalize () löscht Throwable {Super.Finalize (); System.out.println ("in einem Finalize"); }} ## Das Ausgabeergebnis ist:
Ein Objekt wurde noch nicht recycelt.
Dies bestätigt die obige Erklärung.
4.PhantomReference
Im Vergleich zu Softretreferenz oder Schwachanlagen spiegeln sich die Hauptunterschiede in der Phantomreferenz in den folgenden Punkten wider:
1. Phantomreferenz hat nur einen Konstruktor -Phantomreferenz (t Referenz, Referenzqueue <? Super t> q), sodass Phantomreferenz in Kombination mit Referenzqueue verwendet werden muss;
2. Unabhängig davon, ob es einen starken Hinweis auf das Indikatorobjekt auf Phantomreferenz gibt, gibt die Get () -Methode der Phantomreferenz das Ergebnis Null zurück.
öffentliche Klasse Referencetest {public static void main (String [] args) {a = new a (); Referenzqueue <a> rq = new referencequeue <a> (); PhantomReference <a> pra = new PhantomReference <a> (a, rq); System.out.println ("pra.get ():" + pra.get ()); a = null; System.gc (); try {thread.sleep (1); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("RQ item:" + rq.poll ()); }} Klasse A {} ## Das Ausgabeergebnis ist:
pra.get (): nullrq item: java.lang.ref.phantomreference@1da12fc0
Der Thread.Sleep (1); In der Code fungiert genauso wie im obigen Beispiel, und beide stellen sicher, dass der Müllsammlungs -Thread ausgeführt werden kann. Andernfalls werden virtuelle Verweise auf das Indikatorobjekt, das den Müllsammlungsprozess eingeben, ohne tatsächlich Müll gesammelt zu werden, nicht zur Phantomreferenz hinzugefügt.
Wie bei Wecreference ändert PhantomReferenference den Zeitpunkt der Müllsammlung des angegebenen Objekts nicht. Es kann der Schluss gezogen werden, dass die Funktion von Referenzqueue hauptsächlich zum Anhören der Sozidreferenz-/Schwachreferenz-/Phantomreferenz verwendet wird, die angibt, ob das Objekt Müll gesammelt wurde.
Das obige ist der vollständige Inhalt der umfassenden Analyse von Java/Android -Referenztypen und -nutzungen, die Sie vom Herausgeber zur Verfügung gestellt haben. Ich hoffe, es wird Ihnen hilfreich sein und wulin.com mehr ~ unterstützen ~