Heim  >  Artikel  >  Java  >  Eine kurze Diskussion über einige grundlegende Konzepte des GC-Garbage Collectors von Java

Eine kurze Diskussion über einige grundlegende Konzepte des GC-Garbage Collectors von Java

高洛峰
高洛峰Original
2017-01-17 15:53:381331Durchsuche

1. Grundlegender Recycling-Algorithmus

1. Referenzzählung
Ein relativ alter Recycling-Algorithmus. Das Prinzip besteht darin, dass dieses Objekt über eine Referenz verfügt, wodurch die Anzahl erhöht wird und das Löschen einer Referenz die Anzahl verringert. Bei der Garbage Collection werden nur Objekte mit der Anzahl 0 gesammelt. Das Fatalste an diesem Algorithmus ist, dass er das Problem der Zirkelverweise nicht bewältigen kann.
2. Mark-Sweep (Mark-Sweep)
Dieser Algorithmus wird in zwei Stufen ausgeführt. Die erste Phase markiert alle referenzierten Objekte beginnend mit dem Referenzwurzelknoten, und die zweite Phase durchläuft den gesamten Heap und löscht nicht markierte Objekte. Dieser Algorithmus erfordert das Anhalten der gesamten Anwendung und verursacht gleichzeitig eine Speicherfragmentierung.
3. Kopieren
Dieser Algorithmus teilt den Speicherplatz in zwei gleiche Bereiche auf und verwendet jeweils nur einen davon. Bei der Garbage Collection wird der aktuell genutzte Bereich durchquert und die verwendeten Objekte in einen anderen Bereich kopiert. Dieser Algorithmus verarbeitet jedes Mal nur die verwendeten Objekte, sodass der Kopieraufwand relativ gering ist. Gleichzeitig kann der entsprechende Speicher nach dem Kopieren organisiert werden, es treten jedoch Probleme mit der „Fragmentierung“ auf. Natürlich liegt auch der Nachteil dieses Algorithmus auf der Hand, nämlich dass er doppelt so viel Speicherplatz benötigt.
4. Mark-Compact
Dieser Algorithmus vereint die Vorteile der „Mark-Clear“- und „Copy“-Algorithmen. Es ist außerdem in zwei Phasen unterteilt. Die erste Phase beginnt am Wurzelknoten und markiert alle referenzierten Objekte. Die zweite Phase durchläuft den gesamten Heap, löscht nicht markierte Objekte und „komprimiert“ überlebende Objekte in einem der Heaps und entlädt sie der Reihe nach . Dieser Algorithmus vermeidet das Fragmentierungsproblem von „Mark-and-Sweep“ und vermeidet auch das Platzproblem des „Copy“-Algorithmus.
5. Inkrementelle Sammlung (Inkrementelles Sammeln)
Implementieren Sie den Garbage Collection-Algorithmus, dh führen Sie die Garbage Collection durch, während die Anwendung ausgeführt wird. Ich weiß nicht, warum der Collector in JDK5.0 diesen Algorithmus nicht verwendet.
6. Generational Collecting

Ein Garbage-Collection-Algorithmus, der auf der Analyse des Objektlebenszyklus basiert. Teilen Sie Objekte in junge Generation, alte Generation und persistente Generation ein und verwenden Sie unterschiedliche Algorithmen (eine der oben genannten Methoden), um Objekte mit unterschiedlichen Lebenszyklen zu recyceln. Aktuelle Garbage Collectors (ab J2SE1.2) verwenden alle diesen Algorithmus.

1. Junge (junge Generation)
Die junge Generation ist in drei Bereiche unterteilt. Ein Eden-Bereich und zwei Survivor-Bereiche. Die meisten Objekte werden im Eden-Bereich generiert. Wenn der Eden-Bereich voll ist, werden die überlebenden Objekte in den Survivor-Bereich kopiert (einer der beiden). Wenn dieser Survivor-Bereich voll ist, werden die überlebenden Objekte in diesem Bereich in einen anderen Survivor-Bereich kopiert , Wenn es voll ist, werden Objekte, die aus dem ersten Survivor-Bereich kopiert wurden und zu diesem Zeitpunkt noch am Leben sind, in den „Tenured“-Bereich kopiert. Es ist zu beachten, dass die beiden Bereiche von Survivor symmetrisch sind und keine sequentielle Beziehung haben. Daher können gleichzeitig Objekte aus Eden und Objekte aus dem vorherigen Survivor im selben Bereich vorhanden sein, jedoch nur Objekte, die aus dem ersten kopiert wurden Bereich werden in den alten Bereich kopiert, zu dem Survivor gekommen ist. Außerdem ist einer der Survivor-Bereiche immer leer.
2. Tenured (alte Generation)
Die alte Generation speichert Objekte, die von der jungen Generation überdauern. Im Allgemeinen speichert die alte Generation Objekte mit längerer Lebensdauer.
3. Perm (persistente Generierung)
Wird zum Speichern statischer Dateien verwendet, jetzt Java-Klassen, Methoden usw. Die persistente Generierung hat keine wesentlichen Auswirkungen auf die Speicherbereinigung, aber einige Anwendungen können einige Klassen dynamisch generieren oder aufrufen, z. B. Ruhezustand usw. In diesem Fall muss ein relativ großer persistenter Generierungsraum eingerichtet werden, um diese neu hinzugefügten Klassen währenddessen zu speichern Betrieb. Die Größe der persistenten Generation wird mit -XX:MaxPermSize= festgelegt.


2. GC-Typen
Es gibt zwei Arten von GC: Scavenge GC und Full GC.

1. Scavenge GC
Im Allgemeinen wird Scavenge GC ausgelöst, wenn ein neues Objekt generiert wird und sich nicht um Platz in Eden bewirbt. Der Eden-Bereich des Heaps besteht aus GC-fähigen, nicht überlebenden Objekten werden gelöscht und die verbleibenden Surviving-Objekte werden in den Survivor-Bereich verschoben. Dann organisieren Sie die beiden Bereiche von Survivor.
2. Vollständiger GC
Vervollständigen Sie den gesamten Heap, einschließlich Young, Tenured und Perm. Full GC ist langsamer als Scavenge GC, daher sollte Full GC so weit wie möglich reduziert werden. Die folgenden Gründe können zu einer vollständigen GC führen:
* Tenured ist ausgefüllt
* Perm-Feld ist ausgefüllt
* System.gc() wird explizit aufgerufen
* Heap-Felder werden nach der letzten GC-Dynamik zugewiesen Änderungen in der Strategie


Demonstration des Generationen-Garbage-Collection-Prozesses

1.
>

2.

Eine kurze Diskussion über einige grundlegende Konzepte des GC-Garbage Collectors von Java

3.

Eine kurze Diskussion über einige grundlegende Konzepte des GC-Garbage Collectors von Java

4.

Eine kurze Diskussion über einige grundlegende Konzepte des GC-Garbage Collectors von Java

2. Müllsammler


Es gibt derzeit drei Haupttypen von Müllsammlern : Serieller Kollektor, paralleler Kollektor, gleichzeitiger Kollektor.

1. Der serielle Kollektor

verwendet einen einzigen Thread, um die gesamte Garbage-Collection-Arbeit abzuwickeln, da keine Multi-Thread-Interaktion erforderlich ist und daher effizienter ist. Die Vorteile mehrerer Prozessoren stehen jedoch nicht zur Verfügung, sodass dieser Kollektor für Maschinen mit einem Prozessor geeignet ist. Selbstverständlich kann dieser Collector auch auf Multiprozessormaschinen mit kleinen Datenmengen (ca. 100 MB) eingesetzt werden. Kann mit -XX:+UseSerialGC aktiviert werden.

2. Paralleler Collector
1. Führen Sie eine parallele Garbage-Collection für die junge Generation durch und verkürzen Sie so die Garbage-Collection-Zeit. Wird normalerweise auf Multithread-Multiprozessormaschinen verwendet. Verwenden Sie zum Öffnen -XX:+UseParallelGC. Der Parallelkollektor wurde im sechsten Update von J2SE5.0 eingeführt und in Java SE6.0 erweitert – er kann die alte Generation für die parallele Sammlung stapeln. Wenn die alte Generation keine gleichzeitige Sammlung verwendet, wird ein einzelner Thread für die Speicherbereinigung verwendet, wodurch die Erweiterungsmöglichkeiten eingeschränkt werden. Öffnen Sie mit -XX:+UseParallelOldGC.
2. Verwenden Sie -XX:ParallelGCThreads=, um die Anzahl der Threads für die parallele Garbage Collection festzulegen. Dieser Wert kann mit der Anzahl der Prozessoren auf der Maschine gleichgesetzt werden.
3. Dieser Collector kann wie folgt konfiguriert werden:
* Maximale Garbage-Collection-Pause: Geben Sie die maximale Pausenzeit während der Garbage-Collection an, angegeben durch -XX:MaxGCPauseMillis=. ist Millisekunden. Wenn dieser Wert angegeben wird, werden die Heap-Größe und die Speicherbereinigungsparameter angepasst, um den angegebenen Wert zu erreichen. Das Festlegen dieses Werts kann den Durchsatz Ihrer Anwendung verringern.
* Durchsatz: Der Durchsatz ist das Verhältnis der Garbage-Collection-Zeit zur Nicht-Garbage-Collection-Zeit, festgelegt durch -XX:GCTimeRatio=, die Formel ist 1/(1+N). Beispielsweise bedeutet -XX:GCTimeRatio=19, dass 5 % der Zeit für die Speicherbereinigung verwendet werden. Der Standardwert ist 99, was bedeutet, dass 1 % der Zeit für die Speicherbereinigung verwendet wird.

3. Der gleichzeitige Kollektor
kann sicherstellen, dass die meisten Arbeiten gleichzeitig ausgeführt werden (die Anwendung wird nicht angehalten) und die Speicherbereinigung nur für kurze Zeit angehalten wird. Dieser Kollektor ist für mittlere und hohe Anforderungen geeignet -Endanwendungen mit hohen Anforderungen an die Reaktionszeit. Groß angelegte Anwendungen. Einschalten mit -XX:+UseConcMarkSweepGC.
1. Der gleichzeitige Collector reduziert hauptsächlich die Pausenzeit der alten Generation. Er verwendet einen unabhängigen Garbage-Collection-Thread, um erreichbare Objekte zu verfolgen, ohne die Anwendung zu stoppen. Während jedes Garbage Collection-Zyklus der alten Generation hält der gleichzeitige Collector die gesamte Anwendung zu Beginn der Sammlung kurz an und pausiert während der Sammlung erneut. Die zweite Pause ist etwas länger als die erste, in der mehrere Threads gleichzeitig die Garbage Collection durchführen.
2. Der gleichzeitige Kollektor nutzt den Prozessor im Austausch für kurze Pausenzeiten. Auf einem System mit N Prozessoren verwendet der gleichzeitige Sammlungsteil K/N verfügbare Prozessoren für das Recycling. Im Allgemeinen gilt 13. Verwenden Sie den Concurrent Collector auf einem Host mit nur einem Prozessor und stellen Sie ihn auf den inkrementellen Modus ein, um kürzere Pausenzeiten zu erzielen.
4. Floating Garbage: Da die Garbage Collection durchgeführt wird, während die Anwendung ausgeführt wird, kann nach Abschluss der Garbage Collection etwas Müll erzeugt werden, was zu „Floating Garbage“ führt, der im nächsten Garbage Collection-Zyklus gesammelt werden muss . Verlieren. Daher benötigt der gleichzeitige Collector im Allgemeinen 20 % reservierten Speicherplatz für diesen schwebenden Müll.
5. Fehler im gleichzeitigen Modus: Der gleichzeitige Kollektor sammelt, wenn die Anwendung ausgeführt wird. Daher muss sichergestellt werden, dass der Heapspeicher über genügend Speicherplatz verfügt, damit das Programm ihn während der Speicherbereinigung verwenden kann Die Müllabfuhr ist abgeschlossen. In diesem Fall tritt ein „Parallelitätsmodusfehler“ auf und die gesamte Anwendung wird zur Speicherbereinigung angehalten.
6. Starten Sie den Concurrent Collector: Da die Concurrent Collection erfasst wird, während die Anwendung ausgeführt wird, müssen Sie sicherstellen, dass genügend Speicherplatz für das Programm vorhanden ist, bevor die Sammlung abgeschlossen ist, andernfalls tritt ein „Concurrent Mode Failure“ auf. Geben Sie durch die Einstellung -XX:CMSInitiatingOccupancyFraction= an, wie viel verbleibender Heap vorhanden ist, um mit der Ausführung der gleichzeitigen Sammlung zu beginnen

4. Serieller Prozessor:
--Anwendbare Situation: Datenvolumen Relativ klein (ca. 100 MB); eine Anwendung, die auf einem einzelnen Prozessor läuft und keine Anforderungen an die Reaktionszeit stellt.
--Nachteile: Kann nur für kleine Anwendungen verwendet werden
* Parallelprozessor:
--Anwendbare Situationen: „hohe Anforderungen an den Durchsatz“, mittlere und große Anwendungen mit mehreren CPUs und keine Anforderungen an die Reaktionszeit der Anwendung Große Anwendungen. Beispiele: Hintergrundverarbeitung, wissenschaftliches Rechnen.
--Nachteil: Reaktionszeit der Anwendung kann länger sein
* Gleichzeitiger Prozessor:
--Anwendbare Situation: „hohe Anforderungen an die Reaktionszeit“, mehrere CPUs, hohe Anforderungen an die Reaktionszeit der Anwendung Mittlere und große Anwendungen. Beispiele: Webserver/Anwendungsserver, Telekommunikationsvermittlung, integrierte Entwicklungsumgebung.

3. Grundprinzipien von GC
GC (Garbage Collection) ist der Garbage Collector in JAVA/.NET.
Java wurde aus C++ entwickelt. Es hat einige umständliche und fehleranfällige Dinge in C++ aufgegeben und das Konzept von Zählern eingeführt. Einer davon ist der GC-Mechanismus (C# entlehnt von JAVA).
Programmierer sind anfällig für Probleme Orte, vergessenes oder falsches Speicherrecycling können zu Instabilität oder sogar zum Absturz des Programms oder Systems führen. Die von Java bereitgestellte GC-Funktion kann automatisch überwachen, ob das Objekt den Zweck der automatischen Speicherwiederverwendung überschreitet Eine Möglichkeit, zugewiesenen Speicher freizugeben. Zeigen Sie, wie es geht. Daher ist die Speicherverwaltung von Java eigentlich die Verwaltung von Objekten, einschließlich der Zuweisung und Freigabe von Objekten.
Ordnen Sie Objekte mit dem neuen Schlüsselwort zu. Weisen Sie beim Freigeben eines Objekts einfach alle Verweise auf das Objekt zu, damit das Programm nicht mehr auf das Objekt zugreifen kann Verantwortlich für die Rückgewinnung des Speicherplatzes aller „nicht erreichbaren“ Objekte.
Wenn der Programmierer bei GC ein Objekt erstellt, beginnt der GC, die Adresse, Größe und Verwendung des Objekts zu überwachen. Normalerweise verwendet GC einen gerichteten Graphen, um alle Objekte im Heap aufzuzeichnen und zu verwalten. Auf diese Weise wird bestimmt, welche Objekte „erreichbar“ und welche „nicht erreichbar“ sind. Wenn der GC feststellt, dass einige Objekte „nicht erreichbar“ sind, ist der GC für die Rückgewinnung dieser Speicherplätze verantwortlich. Um jedoch sicherzustellen, dass GC auf verschiedenen Plattformen implementiert werden kann, schreibt die Java-Spezifikation viele Verhaltensweisen von GC nicht strikt vor. Beispielsweise gibt es keine klaren Vorschriften zu wichtigen Themen wie der Art des zu verwendenden Recyclingalgorithmus und dem Zeitpunkt des Recyclings. Daher verfügen verschiedene JVM-Implementierer häufig über unterschiedliche Implementierungsalgorithmen. Dies bringt auch große Unsicherheit in die Entwicklung von Java-Programmierern. In diesem Artikel werden verschiedene Probleme im Zusammenhang mit der GC-Arbeit untersucht und versucht, die negativen Auswirkungen dieser Unsicherheit auf Java-Programme zu verringern.

4. GC-Generationsaufteilung
Der Heap im JVM-Speichermodell ist in zwei große Blöcke unterteilt, einer ist die junge Generation und der andere ist die alte Generation

Eine kurze Diskussion über einige grundlegende Konzepte des GC-Garbage Collectors von Java

1) In Young Generation gibt es einen Raum namens Eden Space, der hauptsächlich zum Aufbewahren neuer Objekte verwendet wird. Es gibt auch zwei Survivor Spaces (von, bis). Sie werden zum Aufbewahren verwendet Jedes Mal Gegenstände, die das Recycling überleben.
2) In der alten Generation werden hauptsächlich Speicherobjekte mit langen Lebenszyklen in Anwendungen gespeichert.
3) Im Young Generation-Block verwendet die Speicherbereinigung im Allgemeinen den Kopieralgorithmus, der schnell ist. Bei jedem GC werden die überlebenden Objekte zunächst von Eden in einen SurvivorSpace kopiert. Wenn der Survivor Space voll ist, werden die verbleibenden Live-Objekte direkt in OldGeneration kopiert. Daher wird nach jedem GC der Eden-Speicherblock gelöscht.
4) Im Block der alten Generation verwendet die Garbage Collection im Allgemeinen den Mark-Compact-Algorithmus, der langsamer ist, aber den Speicherbedarf reduziert.
5) Die Garbage Collection ist in mehrere Ebenen unterteilt. Level 0 ist eine vollständige (vollständige) Garbage Collection, die den Müll im OLD-Segment recycelt. Level 1 oder höher ist eine teilweise Garbage Collection, die nur den Müll in Young recycelt . Speicherüberlauf tritt normalerweise auf, wenn immer noch kein Speicherplatz für neue Java-Objekte vorhanden ist, nachdem das ALTE Segment oder Perm-Segment durch Müll gesammelt wurde.

5. Inkrementeller GC
Inkrementeller GC ist ein GC, der normalerweise von einem oder einer Gruppe von Prozessen in der JVM implementiert wird. Er selbst belegt auch denselben Heap-Speicherplatz wie das Benutzerprogramm und beansprucht auch CPU.
Während der GC-Prozess ausgeführt wird, wird die Ausführung der Anwendung gestoppt. Wenn der GC über einen längeren Zeitraum ausgeführt wird, können Benutzer daher die Pause des Java-Programms spüren. Wenn der GC jedoch zu kurz ausgeführt wird, ist die Objektrecyclingrate möglicherweise zu niedrig, was bedeutet, dass es immer noch viele gibt Objekte, die recycelt werden sollten, aber nicht recycelt wurden, beanspruchen immer noch viel Speicher. Daher muss beim Entwurf von GC ein Kompromiss zwischen Pausenzeit und Wiederherstellungsrate geschlossen werden. Eine gute GC-Implementierung ermöglicht es Benutzern, die Einstellungen zu definieren, die sie benötigen. Beispielsweise reagieren einige Geräte mit begrenztem Speicher sehr empfindlich auf die Speichernutzung. Sie hoffen, dass der GC den Speicher genau zurückgewinnen kann, und die Geschwindigkeit des Programms ist ihm egal. Andere Echtzeit-Onlinespiele können keine langen Programmunterbrechungen zulassen.
Inkrementelle GC verwendet einen bestimmten Recycling-Algorithmus, um eine lange Unterbrechung in viele kleine Unterbrechungen aufzuteilen. Auf diese Weise wird die Auswirkung von GC auf Benutzerprogramme verringert. Obwohl inkrementelle GC hinsichtlich der Gesamtleistung möglicherweise nicht so effizient ist wie normale GC, kann sie die maximale Pausenzeit des Programms reduzieren.
Die von Sun JDK bereitgestellte HotSpot-JVM unterstützt inkrementelle GC. Der Standard-GC-Modus von HotSpot JVM besteht darin, keine inkrementelle GC zu verwenden. Um die inkrementelle GC zu starten, müssen wir beim Ausführen des Java-Programms den Parameter -Xincgc hinzufügen.
HotSpot JVM inkrementelle GC wird mithilfe des Train GC-Algorithmus implementiert. Seine Grundidee besteht darin, alle Objekte im Heap entsprechend ihrer Erstellung und Verwendung zu gruppieren und häufig verwendete und relevante Objekte in einer Gruppe zu platzieren , und die Gruppen werden während des Programmablaufs kontinuierlich angepasst. Wenn GC ausgeführt wird, recycelt es immer zuerst die ältesten Objekte (auf die in letzter Zeit selten zugegriffen wurde). Wenn die gesamte Gruppe recycelbar ist, recycelt der GC die gesamte Gruppe. Auf diese Weise stellt jeder GC-Lauf nur einen bestimmten Anteil nicht erreichbarer Objekte wieder her, um den reibungslosen Ablauf des Programms sicherzustellen.

Weitere Artikel zu einigen grundlegenden Konzepten des GC-Garbage Collectors von Java finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn