1. Java -Speichermodell
Bei der Ausführung eines Programms unterteilt die java virtuelle Maschine den Speicher, den sie verwaltet, in mehrere Datenbereiche. Die Verteilung dieser Datenbereiche ist in der folgenden Abbildung dargestellt:
Programmzähler: Ein kleiner Speicherbereich, der auf den aktuell ausgeführten Bytecode zeigt. Wenn der Thread eine Java -Methode ausführt, erfasst dieser Zähler die Adresse der zu verwendenden Bytecode -Anweisung des Virtual Machine. Wenn die native Methode ausgeführt wird, ist der Rechnerwert leer.
Java Virtual Machine Stack: Threads sind privat und ihr Lebenszyklus stimmt mit Threads überein. Wenn jede Methode ausgeführt wird, wird ein Stack -Frame erstellt, um Informationen wie lokale variable Tabellen, Operand -Stapel, dynamische Links, Methodenausgänge usw. zu speichern.
Lokaler Methodenstapel: Die Funktionen ähneln dem virtuellen Maschinenstapel, außer dass der virtuelle Maschinenstapel Java -Methodendienste für die virtuelle Maschine durchführt, während der lokale Methodenstack die verwendete native Methode bedient.
Java Heap: Es ist das größte Stück Virtual Machine Management -Speicher, das von allen Threads geteilt wird. Dieser Bereich wird verwendet, um Objektinstanzen zu speichern, und in diesem Bereich werden fast alle Objekte zugewiesen. Der Java Heap ist der Hauptbereich des Speicherrecyclings. Aus der Sicht des Speicherrecyclings kann der Java -Haufen auch in: die neue Generation und die alte Generation unterteilt werden, da die meisten aktuellen Sammler Generationensammlungsalgorithmen verwenden. Wenn es ein wenig unterteilt ist, kann es in Eden Space, vom Survivor Space bis zum Survivor -Raum usw. unterteilt werden. Nach der Spezifikation der virtuellen Maschine von Java kann der Java -Haufen physisch diskontinuierlich sein, solange er logisch kontinuierlich ist.
Methodenbereich: Wie Java wird er von verschiedenen Threads gemeinsam genutzt und verwendet, um Daten wie Klasseninformationen zu speichern, die von der virtuellen Maschine geladen wurden, immer auf statische Variablen, Code, die vom Instant Compiler zusammengestellt wurden.
Laufzeit konstanter Pool und Laufzeitkonstante Pool ist Teil des Methodenbereichs. Neben der Klassenversion, Felder, Methoden, Schnittstellen und anderen Beschreibungsinformationen gibt es auch einen konstanten Pool in der Klassendatei, mit dem verschiedene buchstäbliche und symbolische Referenzen gespeichert werden, die während der Zusammenstellungsperiode erzeugt werden. Während der Laufzeit können neue Konstanten in den konstanten Pool gestellt werden. Die am häufigsten verwendete Methode der Streichelklasse ist die praktische () -Methode. Wenn eine String -Instanz Praktikant aufruft, findet Java, ob es im konstanten Pool die gleichen Unicode -String -Konstanten gibt. Wenn ja, gibt es seine Referenz zurück; Wenn nicht, fügen Sie einen Unicode hinzu, der der Instanzzeichenfolge entspricht, und gibt seine Referenz zurück.
2. wie man das Müllobjekt bestimmt
Es gibt mehrere Objektinstanzen, die im Java -Haufen gespeichert sind. Bevor der Müllsammler den Haufen recycelt, muss er zunächst bestimmen, welche Objekte noch "lebendig" sind und welche "tot" sind, dh Objekte, die auf keinen Fall verwendet werden.
Zitatzählung
Die Zitierzählmethode ist einfach zu implementieren und effizient und in den meisten Fällen ein guter Algorithmus. Das Prinzip lautet: Fügen Sie dem Objekt einen Referenzzähler hinzu. Immer wenn es einen Ort gibt, an dem das Objekt verweist, wird der Zähler durch 1 erhöht. Wenn die Referenz fehlschlägt, wird der Zähler um 1. reduziert. Wenn der Zählerwert 0 beträgt, bedeutet dies, dass das Objekt nicht mehr verwendet wird. Es ist zu beachten, dass die Referenzzählmethode schwierig ist, das Problem der gegenseitigen Referenz zwischen Objekten zu lösen, und die virtuellen Mainstream -Java -Maschinen verwenden die Referenzzählmethode nicht, um den Speicher zu verwalten.
Zugänglichkeitsanalysealgorithmus
Die Grundidee dieses Algorithmus besteht darin, durch eine Reihe von Objekten nach unten zu suchen, die als "GC -Wurzeln" als Ausgangspunkt aus diesen Knoten bezeichnet werden. Der durchsuchende Weg wird als Referenzkette bezeichnet. Wenn ein Objekt nicht mit GC -Wurzeln ohne Referenzkette verbunden ist (in den Worten der Graphentheorie, von GC -Wurzeln zu diesem Objekt, das nicht erreichbar ist), wird bewiesen, dass dieses Objekt nicht verfügbar ist. Wie in der Abbildung gezeigt, sind Objekte 5, Objekt 6 und Objekt 7, obwohl sie miteinander verbunden sind, für GC -Wurzeln nicht erreichbar, sodass sie als recycelbare Objekte beurteilt werden.
In der Java -Sprache sind die folgenden Objekte, die als GC -Wurzeln verwendet werden können, umfassen:
Objekt, auf das im Stack Virtual Machine (lokale variable Tabelle im Stapelrahmen) verwiesen wird.
Objekt, auf das das statische Attribut der Klasse im Methodenbereich verwiesen wird.
Objekt, das von Konstanten im Methodenbereich verwiesen wird.
Objekte, auf die JNI (dh die allgemeine native Methode) im lokalen Methodenstapel verwiesen wird.
Nun ist die Frage, ob der Algorithmus zur Zugänglichkeitsanalyse ein kreisförmiges Referenzproblem zwischen Objekten hat? Die Antwort lautet Ja, das heißt, es wird kein Problem der kreisförmigen Referenz zwischen Objekten geben. GC Root ist ein speziell definierter "Startpunkt" außerhalb des Objektdiagramms und kann nicht von Objekten im Objektdiagramm referenziert werden.
Sterben oder nicht sterben
Selbst unerreichbare Objekte im Algorithmus zur Zugänglichkeitsanalyse sind nicht "sterben". Zu diesem Zeitpunkt befinden sie sich vorübergehend im Stadium der "Bewährung". Um ein Objekt wirklich tot zu erklären, muss es mindestens zwei Markierungsprozesse durchlaufen: Wenn das Objekt nach der Durchführung der Zugänglichkeitsanalyse keine Referenzkette mit GC -Wurzeln angeschlossen ist, wird es zum ersten Mal markiert und filtriert. Die Filterbedingung ist, ob es für dieses Objekt erforderlich ist, um die Finapze () -Methode auszuführen. Wenn das Objekt die finapze () -Methode nicht überschreibt oder die virtuelle Maschine die virtuelle Maschine als "keine Notwendigkeit ausführen" bezeichnet. Im Programm können Sie Finapze () überschreiben, um einen "aufregenden" Selbstverlustprozess zu erstellen, aber dies ist nur eine Chance.
/** * Dieser Code zeigt zwei Punkte: * 1. Objekte können sich selbst retten, wenn sie GC sind. * 2. Es besteht nur eine Chance auf Selbstbeschaffung, da die finapze () -Methode eines Objekts höchstens vom System höchstens automatisch aufgerufen wird. pubpc void isapve () {System.out.println ("Ja, ich bin immer noch apve :)"); } @Override protected void finapze () wirft Throwable {Super.finapze (); System.out.println ("Finapze Mehtod ausgeführt!"); Finapzeescapegc.save_hook = this; } pubpc static void main (String [] args) löst Throwable {Save_Hook = New FinapzeescapeGC () aus; // Das Objekt speichert sich erfolgreich zum ersten Mal Save_hook = null; System.gc (); // Da die Finapze -Methode eine niedrige Priorität hat, machen Sie 0,5 Sekunden lang, um auf IT -Thread zu warten. Sleep (500); if (Save_Hook! } else {system.out.println ("Nein, ich bin tot :(");} // Der folgende Code ist genau das gleiche wie das oben, aber diesmal ist der Selbstbereich fehlgeschlagen. Save_hook = null; system.gc (); // weil die Finapze-Methode eine niedrige Priorität hat. SAVE_HOOK.ISAPVE ();Das laufende Ergebnis ist:
Finapze Mehtod wurde ausgeführt! Ja, ich bin immer noch Apve :) Nein, ich bin tot :(
Sprechen wir über Zitate
Unabhängig davon, ob die Anzahl der Referenzen eines Objekts durch einen Referenzzählalgorithmus beurteilt wird, oder festzustellen, ob die Referenzkette des Objekts durch einen Algorithmus zur Zugänglichkeitsanalyse erreichbar ist und feststellt, ob das Überleben des Objekts mit "Referenz" zusammenhängt. Vor JDK 1.2 war die Definition von Referenzen in Java sehr traditionell: Wenn der in Referenztypdaten gespeicherte Wert die Startadresse eines anderen Speichers darstellt, wird gesagt, dass dieses Speicherstück eine Referenz darstellt. Nach JDK 1.2 erweiterte Java das Referenzkonzept und unterteilte Referenzen in vier Typen: starke Referenz, weiche Referenz, schwache Referenz und Phantomreferenz. Die Stärke dieser vier Referenzarten schwächte nach und nach.
• Starkes Zitat bezieht sich auf Referenzen, die im Programmcode üblich sind, z. B. "Object OBJ = New Object ()". Solange das starke Zitat noch existiert, wird der Müllsammler das referenzierte Objekt niemals recyceln.
• Weiche Referenzen werden verwendet, um einige nützliche, aber nicht notwendige Objekte zu beschreiben. Für sanfte Referenzbeschaffungsobjekte werden diese Objekte für ein zweites Recycling im Recycling -Bereich aufgeführt, bevor das System kurz vor dem Speicherüberlauf wird. Wenn nicht genügend Speicher für dieses Recycling vorhanden ist, wird eine Ausnahme des Speicherüberlaufs ausgelöst. Nach JDK 1.2 wird die Softreference -Klasse bereitgestellt, um weiche Referenzen zu implementieren.
• Schwache Referenzen werden auch verwendet, um nicht wesentliche Objekte zu beschreiben, aber ihre Stärke ist schwächer als weiche Referenzen. Objekte, die mit schwachen Referenzen verbunden sind, können nur bis zur nächsten Müllsammlung überleben. Wenn der Müllsammler funktioniert, werden Objekte, die nur mit schwachen Referenzen verbunden sind, unabhängig davon, ob das aktuelle Speicher ausreicht. Nach JDK 1.2 wird die WeaCreference -Klasse vorgesehen, um schwache Referenzen umzusetzen.
• Hohlraumzitate werden auch als Ghost -Zitate oder Phantomzitate bezeichnet und sind die schwächste Zitierbeziehung. Ob ein Objekt eine virtuelle Referenz hat, hat überhaupt keinen Einfluss auf seine Überlebenszeit und es ist auch nicht möglich, eine Objektinstanz durch virtuelle Referenz zu erhalten. Der einzige Zweck, virtuelle Referenzverbände für ein Objekt einzurichten, besteht darin, eine Systembenachrichtigung zu erhalten, wenn das Objekt vom Sammler recycelt wird. Nach JDK 1.2 wird die PhantomReference -Klasse zur Implementierung virtueller Referenzen bereitgestellt.
Beispiel für sanfte Referenzverwendung:
Paket JVM; importieren java.lang.ref.sofTreference; Klasse node {pubpc String msg = "";} Pubpc -Klasse Hallo {Pubpc static void main (string [] args) {node node1 = new node (); // starker Referenzknoten1.msg = "Node1"; Softrreference <Knode> node2 = new Softreference <node> (Node1); // Soft Referenz node2.get (). Msg = "node2"; system.out.println (node1.msg);Das Ausgangsergebnis ist:
node2Node2
3. Typischer Müllsammleralgorithmus
1.Mark-Sweep (Mark-Clear) -Algorithmus
Dies ist der grundlegendste Algorithmus zur Müllsammlung. Der Grund, warum es am grundlegendsten ist, ist, dass es am einfachsten ist, die einfachste und die einfachste Idee zu implementieren. Der markierte Algorithmus ist in zwei Phasen unterteilt: die Markierungsphase und die Clearing-Stufe. Die Aufgabe der Markierungsphase besteht darin, alle Objekte zu markieren, die recycelt werden müssen, und in der Klärung ist es, den von den markierten Objekten besetzten Raum zu recyceln. Der spezifische Prozess ist in der folgenden Abbildung dargestellt:
Aus der Abbildung ist leicht zu erkennen, dass der Markierungsalgorithmus einfacher zu implementieren ist, aber es gibt ein ernstes Problem, dass es einfach ist, Speicherfragmente zu erzeugen. Zu viele Fragmente können dazu führen, dass bei der Zuweisung von Platz für große Objekte im nachfolgenden Prozess nicht genügend Platz ist und eine neue Müllsammlung im Voraus ausgelöst wird.
2. Algorithmus kopieren
Um die Mängel des Mark-Sweep-Algorithmus zu lösen, wurde der Kopieralgorithmus vorgeschlagen. Es unterteilt den verfügbaren Speicher in zwei gleiche Größe nach Kapazität und verwendet jeweils nur ein Stück. Wenn dieses Stück Speicher aufgebraucht wird, kopieren Sie das immer noch lebende Objekt in ein anderes Stück und räumen Sie dann den gebrauchten Speicherraum sofort auf, sodass Probleme mit der Speicherfragmentierung nicht auftreten. Der spezifische Prozess ist in der folgenden Abbildung dargestellt:
Obwohl dieser Algorithmus einfach zu implementieren, effizient zu laufen und nicht einfach zu erzeugen ist, ist es teuer, den Speicherraum zu verwenden, da der Speicherspeicher auf die Hälfte des ursprünglichen reduziert wird.
Offensichtlich hat die Effizienz des Kopieralgorithmus viel mit der Anzahl der überlebenden Objekte zu tun. Wenn es viele überlebende Objekte gibt, wird die Effizienz des Kopieralgorithmus stark reduziert.
3. Mark-Compact (Mark-Kollation) -Algorithmus
Um die Mängel des Kopierungsalgorithmus zu lösen und den Speicherraum voll auszunutzen, wird der Mark-Compact-Algorithmus vorgeschlagen. Der Algorithmus markiert genauso wie Mark-Sweep, aber nach Abschluss der Marke werden die recycelbaren Objekte nicht direkt aufgeräumt, sondern alle lebenden Objekte zu einem Ende und räumt dann außerhalb der Endgrenze auf den Speicher auf. Der spezifische Prozess ist in der folgenden Abbildung dargestellt:
4. Generationensammlungsalgorithmus
Der Generationskollektionalgorithmus wird derzeit von den meisten JVM -Müllsammlern verwendet. Seine Kernidee besteht darin, das Gedächtnis gemäß dem Lebenszyklus des Überlebens des Objekts in verschiedene Regionen zu unterteilen. Im Allgemeinen ist das Haufenbereich in die alte Generation und die junge Generation unterteilt. Das Merkmal der alten Generation ist, dass nur eine kleine Anzahl von Objekten jedes Mal recycelt werden muss, wenn der Müll gesammelt wird, während das Merkmal der neuen Generation darin besteht, dass eine große Anzahl von Objekten jedes Mal recycelt werden muss, wenn der Müll gesammelt wird. Dann kann der am besten geeignete Sammelalgorithmus gemäß den Merkmalen verschiedener Generationen übernommen werden.
Gegenwärtig übernehmen die meisten Müllsammler den Kopieralgorithmus für die neue Generation, da die meisten Objekte in der neuen Generation jedes Mal recycelt werden müssen, dh die Anzahl der Operationen, die kopiert werden müssen, ist gering, aber in der Realität wird der Raum der neuen Generation nicht gemäß einer Verhältnis von 1: 1 unterteilt. Im Allgemeinen ist die neue Generation in einen größeren Edenraum und zwei kleinere Überlebenderäume unterteilt (normalerweise 8: 1: 1). Jedes Mal, wenn der Eden -Raum und einer der Überlebenden Räume verwendet werden, werden beim Recycling die Objekte, die noch in Eden und Survivor überleben, in einen anderen Überlebendenraum kopiert, und dann werden Eden und die gerade verwendeten Überlebendenräume gereinigt.
Da das Alter lautet, dass jedes Mal nur eine kleine Anzahl von Objekten recycelt wird, wird der Mark-Kompaktalgorithmus im Allgemeinen verwendet.
Die obige kurze Analyse des Java -Speichermodells und der Müllsammlung ist der gesamte Inhalt, den ich mit Ihnen teile. Ich hoffe, Sie können Ihnen eine Referenz geben und ich hoffe, Sie können wulin.com mehr unterstützen.