Die wichtigsten Garbage-Collection-Algorithmen sind: Mark-Clear, Copy und Mark-Organize.
1. Mark-Sweep-Algorithmus
Markieren Sie die zu recycelnden Objekte.
Nachteile des Algorithmus: Effizienzprobleme, die Markierungs- und Löschprozesse sind sehr ineffizient; nach der Erfassung wird eine große Anzahl von Speicherfragmenten generiert, was der Zuordnung großer Objekte nicht förderlich ist.
2. Kopieralgorithmus
Der Kopieralgorithmus teilt den verfügbaren Speicher in zwei gleich große Blöcke A und B auf. Es wird jeweils nur einer davon verwendet Der Speicher von A wird verwendet. Kopieren Sie anschließend die überlebenden Objekte nach B und löschen Sie den Speicher von A. Dies verbessert nicht nur die Effizienz der Markierung, da nur die überlebenden Objekte markiert werden müssen, sondern vermeidet auch das Problem der Speicherfragmentierung die Kosten für die Reduzierung des verfügbaren Speichers auf die Hälfte der ursprünglichen Größe.
3. Mark-Collation-Algorithmus
In der alten Generation ist die Objektüberlebensrate hoch und die Effizienz des Kopieralgorithmus sehr gering. Beim Mark-Compact-Algorithmus werden alle lebenden Objekte markiert und an ein Ende verschoben. Anschließend wird der Speicher außerhalb der Grenze direkt bereinigt.
Während des Erreichbarkeitsanalyseprozesses muss die gesamte Ausführungs-Engine so aussehen, als wäre sie eingefroren, um die mit GC Roots verknüpften Objekte genau herauszufinden Ein bestimmter Zeitpunkt bedeutet, dass alle laufenden Threads angehalten werden und sich die Referenzbeziehung des Objekts nicht weiter ändern kann.
Wie kann man GC Roots schnell aufzählen?
GC-Wurzeln liegen hauptsächlich in globalen Referenzen (Konstanten oder statischen Klasseneigenschaften) und Ausführungskontexten (Referenzen in lokalen Variablentabellen) vor, wenn sie durchsucht werden sehr ineffizient sein.
In HotSpot wird es mithilfe einer Reihe von Datenstrukturen namens OopMap implementiert. Wenn das Laden der Klasse abgeschlossen ist, berechnet HotSpot, welche Art von Daten sich an welchem Offset im Objekt befinden und speichert sie in OopMap. Der über JIT kompilierte lokale Code zeichnet auch auf, welche Stellen im Stapel und in den Registern Referenzen sind. Wenn GC auftritt, können überlebende Objekte schnell durch Scannen der OopMap-Daten identifiziert werden.
Wie führt man GC sicher durch?
Wenn ein Thread ausgeführt wird, kann er für GC nur dann angehalten werden, wenn er einen sicheren Punkt erreicht.
Basierend auf der OopMap-Datenstruktur kann HotSpot die Durchquerung von GC-Roots schnell abschließen. HotSpot generiert jedoch nicht für jede Anweisung eine entsprechende OopMap und zeichnet diese Informationen nur am sicheren Punkt auf.
Daher ist die Wahl des sicheren Punkts sehr wichtig. Wenn er zu niedrig ist, kann dies dazu führen, dass der GC zu lange wartet. Wenn er zu häufig ist, kann dies zu Problemen mit der Laufzeit führen. Die Ausführungszeit der meisten Anweisungen ist sehr kurz, und einige Anweisungen mit langer Ausführungszeit werden normalerweise als sichere Punkte ausgewählt, z. B. Methodenaufrufe, Schleifensprünge und Ausnahmesprünge.
Weitere Informationen zu Safe Point finden Sie in diesem Artikel JVMs Stop The World, Safe Point, Dark Underground World
So lassen Sie alle Threads laufen, wenn GC auftritt. Run to zum nächsten sicheren Punkt und pausieren?
Wenn GC auftritt, wird der Thread nicht direkt unterbrochen, sondern es wird einfach ein Interrupt-Flag gesetzt. Wenn jeder Thread zum sicheren Punkt läuft, fragt er aktiv das Interrupt-Flag ab Stimmt, es wird sich selbst unterbrechen.
Wenn GC auftritt, können laufende Threads zum sicheren Punkt laufen und hängen bleiben, während Threads im Ruhezustand oder im blockierten Zustand zu diesem Zeitpunkt nicht auf die Interrupt-Anfrage reagieren können Gehen Sie zum Anhalten zum sicheren Punkt. In dieser Situation können Sie das Problem über den sicheren Bereich lösen.
Sicherer Bereich bedeutet, dass sich die Referenzbeziehung des Objekts in einem Codeabschnitt nicht ändert. Es ist sicher, GC irgendwo in diesem Bereich zu starten.
1. Wenn ein Thread in den sicheren Bereich gelangt, wird er zunächst als in den sicheren Bereich eingetreten identifiziert >
2. Wenn der Thread die sichere Region verlässt, prüft er, ob die JVM abgeschlossen ist. Andernfalls muss der Thread warten, bis er ein Signal empfängt dass es die sichere Region sicher verlassen kann;
Die Java Virtual Machine-Spezifikation legt nicht fest, wie der Garbage Collector implementiert werden soll. Benutzer können die in den einzelnen Bereichen verwendeten Collectors entsprechend den Systemeigenschaften kombinieren.
Das obige Bild zeigt 7 Sammler verschiedener Generationen. Wenn zwischen zwei eine Verbindung besteht, bedeutet dies, dass sie in Kombination verwendet werden können.
1. Serieller Kollektor (serieller GC)
Serial ist ein Kollektor, der einen einzelnen Thread verwendet und auf der Grundlage eines Kopieralgorithmus arbeitet Sammlung müssen alle anderen Arbeitsthreads angehalten werden. In einer Einzel-CPU-Umgebung kann Serial die Garbage Collection sehr effizient durchführen, da es keinen Thread-Interaktionsaufwand verursacht. Es ist der Standardkollektor für die neue Generation im Client-Modus.
2. ParNew Collector (paralleler GC)
ParNew ist eigentlich eine Multithread-Version von Serial. Zusätzlich zur Verwendung mehrerer Threads für die Garbage Collection Das Verhalten ist das gleiche wie bei „Same as Serial“.
3. Parallel Scavenge Collector (Parallel Recycling GC)
Parallel Scavenge ist ein Collector, der einen Multithread-Kopieralgorithmus verwendet und in der neuen Generation arbeitet Es geht darum, einen kontrollierbaren Durchsatz zu erreichen, der oft als „Durchsatz-zuerst“-Kollektor bezeichnet wird.
Durchsatz = Benutzercode-Laufzeit / (Benutzercode-Laufzeit + Garbage-Collection-Zeit)
Parallel Scavenge bietet zwei Parameter zur präzisen Steuerung des Durchsatzes:
1. -XX : MaxGCPauseMillis legt die maximale Pausenzeit für die Garbage Collection fest
2. -XX: GCTimeRatio legt die Durchsatzgröße fest
4. Serial Old Collector (serieller GC)
Serial Old ist ein Collector, der einen Single-Threaded-Markierungsalgorithmus verwendet und in der alten Generation funktioniert. Er ist der Standard-Collector in der alten Generation im Client-Modus.
5. Parallel Old Collector (Parallel GC)
Parallel Old ist ein Collector, der Multithreading basierend auf dem Mark-Collation-Algorithmus verwendet und in der alten Generation funktioniert. In Situationen, in denen der Durchsatz wichtig und die CPU-Ressourcen empfindlich sind, kann der Collector-Kombination aus Parallel Scavenge und Parallel Old Priorität eingeräumt werden.
6. CMS Collector (Concurrent GC)
CMS (Concurrent Mark Sweep) ist ein Collector, der auf die kürzeste Recycling-Pausezeit abzielt und in der alten Generation funktioniert wird basierend auf dem „Mark-Clear“-Algorithmus implementiert. Der gesamte Prozess ist in die folgenden 4 Schritte unterteilt:
1 Roots können jedoch direkt mit 2 verknüpft werden: Der Prozess der GC Roots Tracing kann mit Benutzer-Threads funktionieren.
3. Anmerkung: Wird verwendet, um den Teil des Datensatzes zu korrigieren, der sich aufgrund der weiteren Ausführung des Benutzerprogramms während der gleichzeitigen Markierung ändert. Bei diesem Prozess werden alle Threads angehalten, die Pausenzeit jedoch viel länger. Die Zeit ist kürzer als die gleichzeitige Markierung.
Gleichzeitige Bereinigung
: Kann mit Benutzer-Threads funktionieren. Nachteile des CMS-Kollektors:
1. Er reagiert empfindlich auf CPU-Ressourcen. In der gleichzeitigen Phase wird er zwar nicht dazu führen, dass Benutzer-Threads angehalten werden, er belegt jedoch einen Teil der Thread-Ressourcen und reduzieren Sie den Gesamtdurchsatz der Anlage. 2. Während der gleichzeitigen Bereinigungsphase kann dieser Teil des Mülls nur im nächsten GC gesammelt werden.
3. CMS basiert auf dem Mark-and-Sweep-Algorithmus, was bedeutet, dass nach Abschluss der Sammlung eine große Anzahl von Speicherfragmenten verursacht wird, was zu einem großen verbleibenden Speicherplatz führen kann Die alte Generation kann jedoch keinen ausreichend großen kontinuierlichen Speicherplatz finden, um das aktuelle Objekt zuzuweisen. Es muss im Voraus eine vollständige GC ausgelöst werden.
Wenn in der JDK1.5-Implementierung die Speicherplatznutzung der alten Generation 68 % erreicht, wird der CMS-Kollektor ausgelöst. Wenn die alte Generation in der Anwendung nicht zu schnell wächst, können Sie den Auslöseprozentsatz durch erhöhen -XX:CMSInitiatingOccupancyFraction-Parameter, wodurch die Anzahl der Speicherwiederverwendungszeiten reduziert und die Systemleistung verbessert wird.
In der JDK1.6-Implementierung wurde der Schwellenwert für das Auslösen des CMS-Collectors auf 92 % erhöht. Wenn der während des CMS-Betriebs reservierte Speicher die Anforderungen von Benutzer-Threads nicht erfüllen kann, kommt es zu einem „Concurrent Mode Failure“. Dies ist der Fall: Die virtuelle Maschine startet den Serial Old Collector, um den Müll der alten Generation zu sammeln. Daher kann dieser Schwellenwert nicht zu hoch eingestellt werden „Bei einem Fehler wird die Leistung beeinträchtigt. Was die Festlegung dieses Schwellenwerts betrifft, muss die Nutzung des Speicherplatzes der alten Generation über einen langen Zeitraum überwacht werden.
7. G1-Kollektor
G1 (Garbage First) ist ein von JDK1.7 bereitgestellter Kollektor, der in der neuen und alten Generation funktioniert und auf „Mark-“ basiert. Der „Collation“-Algorithmus ist implementiert, um Speicherfragmentierungsprobleme nach Abschluss der Sammlung zu vermeiden.
G1-Vorteile: 1. Parallelität und Parallelität: Nutzen Sie mehrere CPUs, um die Pausenzeit von Stop The World zu verkürzen.
2 Sammlung ist erforderlich. Durch Zusammenarbeit können Sie den gesamten Java-Heap verwalten und verschiedene Methoden verwenden, um neu erstellte Objekte zu verarbeiten, Objekte, die über einen bestimmten Zeitraum hinweg überlebt haben und mehrere GCs durchlaufen haben, um bessere Sammlungseffekte zu erzielen3. Speicherplatzintegration: Im Gegensatz zum „Mark-Clear“-Algorithmus von CMS erzeugt G1 während des Betriebs keine Speicherplatzfragmentierung, was dem langfristigen Betrieb von Anwendungen zuträglich ist und nicht dazu führt, dass eine Anwendung nicht möglich ist ausreichend großes Objekt. Der kontinuierliche Speicher löst im Voraus eine vollständige GC aus.
4. Pausenvorhersage: In G1 kann ein vorhersehbares Pausenzeitmodell eingerichtet werden, mit dem Benutzer die für die Speicherbereinigung aufgewendete Zeit klar angeben können ein Zeitabschnitt von M Millisekunden. Die Einschaltdauer sollte N Millisekunden nicht überschreiten.
Bei Verwendung des G1-Kollektors unterscheidet sich das Speicherlayout des Java-Heaps stark von anderen Kollektoren. Der gesamte Java-Heap wird in mehrere unabhängige Bereiche gleicher Größe unterteilt Sie sind alle physisch isoliert und eine Ansammlung von Regionen (nicht unbedingt aufeinanderfolgend). G1 verfolgt den Garbage-Collection-Status jeder Region (Größe des Recyclingraums und Recyclingzeit), führt eine Prioritätenliste und gibt der Region mit dem größten Wert basierend auf der zulässigen Sammelzeit Priorität, um eine Garbage Collection für die gesamte Region zu vermeiden Java-Heap, um sicherzustellen, dass der G1-Kollektor in einer begrenzten Zeit so viel Müll wie möglich sammeln kann.
Aber hier kommt das Problem: Mit dem G1-Kollektor wird ein Objekt in einer Region zugewiesen und kann eine Referenzbeziehung zu jedem Objekt auf dem Java-Heap haben. Wie kann man also feststellen, ob ein Objekt aktiv ist? Ist es notwendig, den gesamten Java-Heap zu scannen? Tatsächlich bestand dieses Problem auch bei früheren Sammlern. Wenn Sie beim Recycling von Objekten der neuen Generation gleichzeitig die alte Generation scannen müssen, wird die Effizienz von Minor GC erheblich verringert.
Für diese Situation bietet die virtuelle Maschine eine Lösung: Die Objektreferenzbeziehung zwischen Regionen im G1-Kollektor und die Objektreferenzbeziehung zwischen der neuen Generation und der alten Generation in anderen Kollektoren werden in der Datenstruktur „Remembered Set“ gespeichert , wird verwendet, um einen vollständigen Heap-Scan zu vermeiden. Jede Region in G1 verfügt über einen entsprechenden Remenbered Set. Wenn die virtuelle Maschine erkennt, dass das Programm Daten vom Referenztyp schreibt, generiert sie eine Schreibbarriere, um den Schreibvorgang vorübergehend zu unterbrechen und zu prüfen, ob sich das durch die Referenz referenzierte Objekt in der befindet Wenn nicht, werden die relevanten Referenzinformationen über CardTable im Remembered Set der Region aufgezeichnet, zu der das referenzierte Objekt gehört.
Diese Dinge über Java GC (1)
Diese Dinge über Java GC (2)
Das Obige ist der Inhalt dieser Dinge über Java GC (2), mehr Verwandte Bitte beachten Sie den Inhalt der chinesischen PHP-Website (www.php.cn)!