Organisieren Sie den Mechanismus von Java GC

Vor kurzem habe ich einen Job im Zusammenhang mit einem Java-Prozess, der viel Speicher benötigt, und ich musste GC kennen, damit ich zusammenfassen kann, was ich untersucht habe. Es ist eine Ära, in der ich nachschaue, aber ich habe es geschrieben, um meine Gedanken zu ordnen. Ich würde es begrüßen, wenn Sie darauf hinweisen könnten, dass die Möglichkeit besteht, dass Sie falsch verstehen.

Hinweis: In diesem Artikel geht es nicht um die neuesten GC-Angelegenheiten, sondern um die klassische Methode.

JVM Zunächst aus dem Grundmechanismus von Java. Java-Prozesse werden auf virtuellen Maschinen ausgeführt, die als JVMs bezeichnet werden. Dieser Mechanismus funktioniert auf verschiedenen Betriebssystemen und ermöglicht die Ausführung von kompiliertem Java-Code (Klassendateien) in verschiedenen Umgebungen, ohne sich um Unterschiede in der Umgebung sorgen zu müssen.

Es gibt verschiedene Arten von JVMs, in diesem Artikel wird jedoch die vom Open JDK verwendete HotSpot-VM vorausgesetzt. (Ich kenne den Unterschied zu anderen JVMs nicht)

Haufenbereich

Der Speicher wird zugewiesen, wenn Sie einen Java-Prozess starten. Der Bereich, der hauptsächlich verwendet wird, wird als Heap-Bereich bezeichnet, und Daten, die sich während der Ausführung der Verarbeitung dynamisch ändern, werden hier grundsätzlich zugeordnet. Es ist wichtig, die Speichernutzung in diesem Heap-Bereich für Anwendungen zu optimieren, die lange Zeit im selben Prozess ausgeführt werden.

Bei Angabe der Größe, die speziell als Option zugewiesen werden soll

-Xms20m -Xmx100m

Wenn Sie angeben Anfangsgröße des dem Heap-Bereich zugewiesenen Speichers: 20 MB Maximale Größe des dem Heap-Bereich zugewiesenen Speichers: 100 MB

Es wird die Einstellung sein.

Unnötiger Speicherbereich

Wenn Sie eine Anwendung erstellen, ohne den Status der Speichernutzung zu kennen, werden nicht mehr verwendete Garbage-Daten (Garbage) erstellt.

In diesem Artikel werde ich ein Beispiel für das Auftreten von Müll auf leicht verständliche Weise vorstellen. https://www.oracle.com/webfolder/technetwork/jp/javamagazine/Java-MA16-GC.pdf

Zum Beispiel, wenn Sie die folgende Klasse haben

class TreeNode {
    public TreeNode left, right;
    public int data;
    TreeNode(TreeNode l, TreeNode r, int d) {
        left = l; right = r; data = d;
    }
    public void setLeft(TreeNode l) { left = l;}
    public void setRight(TreeNode r) {right = r;}
}

Erstellen Sie einen TreeNode wie folgt.

TreeNode left = new TreeNode(null, null, 13);
TreeNode right = new TreeNode(null, null, 19);
TreeNode root = new TreeNode(left, right, 17);

Dies bedeutet, dass der Wurzelknoten auf den linken und rechten Knoten verweist.

Angenommen, Sie haben einen Prozess hinzugefügt, um den richtigen Knoten zu ersetzen.

root.setRight(new TreeNode(null, null, 21));

Dann wird der 19. Knoten, der sich ursprünglich im richtigen Knoten befand, von niemandem referenziert und befindet sich in dem in der folgenden Abbildung gezeigten Zustand.

In diesem Zustand ist die TreeNode-Instanz mit data = 19 ein Objekt, auf das von niemandem verwiesen wird, sodass es zu einem Müll wurde.

Wenn weiterhin nicht verwendete Daten generiert werden, sammelt sich weiterhin nutzloser Speicher an und die Kapazität erreicht schließlich ihre Grenze. Um dies zu verhindern, ist GC (Garbage Collection) als Mechanismus erforderlich, um verschwendeten Speicher im Heap-Bereich automatisch freizugeben.

Rolle von GC und Heap-Bereich

Wie bereits erwähnt, ist GC ein Mechanismus zum Freigeben von unnötigem Speicher. Es überprüft die Daten im Speicher, belässt sie als gültige Daten, wenn eine Referenz vorhanden ist, und gibt sie frei, wenn keine Referenz vorhanden ist, und urteilt, dass dies nicht erforderlich ist. Es ist jedoch ineffizient, den gesamten Speicherplatz einfach zu überprüfen, sodass er intern entsprechend der Existenzdauer der Daten verwaltet wird.

Junge Daten werden als junge Generation bezeichnet, alte Daten werden als alte Generation bezeichnet, und Daten, von denen bekannt ist, dass sie sich weniger wahrscheinlich ändern, werden als permanente Generation bezeichnet.

heap memory (4).png

Grundsätzlich kommt es häufig zu einer Speicherzuweisung, aber die Idee, dass die meisten von ihnen nicht lange leben, wird in neue Daten (junge Generation) und langfristige Referenzdaten (alte Generation) unterteilt. Dies ermöglicht es, nur die in Young Generation enthaltenen Daten effizient zu überprüfen, indem auf den GC abgezielt wird.

Es gibt auch einen Bereich namens Permanent Generation, in dem Informationen zu geladenen Klassen gespeichert werden, die garantiert bis zu einem gewissen Grad gleich bleiben.

Referenz: JDK-Dokumentation öffnen

GC-Zyklus

Es gibt mehrere GC-Algorithmen.

Und so weiter.

Dieses Mal werde ich die in Serial GC und Parallel GC verwendete Methode erläutern.

Der Young-Bereich des Heap-Bereichs ist in Eden und Survivor unterteilt, wie in der folgenden Abbildung gezeigt, und die GC wird durchgeführt, indem jeder Bereich gut genutzt wird. heap memory (7).png

Jeder Bereich hat die folgenden Rollen.

Minor GC

Ein GC, der nur auf die junge Generation abzielt, wird als kleiner GC bezeichnet. Es hat die folgenden Funktionen.

Es ist schwer in Worten zu erklären, deshalb werde ich es mit einer Figur erklären.

Ein kleiner GC tritt auf, wenn neuer Speicher zugewiesen wird und Eden voll ist. Nicht referenzierte Daten werden gelöscht, aber gültige Daten werden in den Survivor-Bereich kopiert. Auch der Eden-Bereich wird komplett leer sein. heap memory (11).png

Wenn Eden in diesem Zustand wieder voll wird, tritt erneut eine geringfügige GC auf und das Ergebnis ist wie in der folgenden Abbildung gezeigt. heap memory (9).png

Diesmal habe ich Survivor 2 nach GC eingegeben. Im Bereich "Überlebende" werden die Daten entweder in den freien Speicherplatz kopiert und 1 und 2 werden hin und her verschoben. Ebenso wie Eden werden Daten gelöscht, auf die nicht aus dem Suvivor-Bereich verwiesen wird.

Als nächstes kommt die Beförderung zum Alten. Jedes Mal, wenn ein GC auftritt, werden die Daten von Young so oft aufgezeichnet, und wenn sie eine bestimmte Anzahl überschreiten, werden sie zu Alt verschoben. heap memory (10).png

Durch mehrmaliges Wiederholen der GC auf diese Weise erfolgt die Bewegung von Jung nach Alt. Diese Nummer kann optional angegeben werden, sodass Sie steuern können, wie oft Sie zu Alt wechseln.

-XX:MaxTenuringThreshold=N

FullGC Ich verstehe, wie Daten von Jung nach Alt übertragen werden, aber allein damit wird die Kapazität von Alt weiter zunehmen und die Kapazität wird irgendwo begrenzt sein. Hier kommt FullGC ins Spiel. FullGC tritt auf, wenn die Zuordnung zu Alt fehlschlägt und den Speicher einschließlich Alt und Jung bereinigt. heap memory (12).png

Dadurch wird Speicherplatz frei, der im Bereich "Alt" nicht mehr benötigt wird, und Sie können die Daten kopieren, die sich im Bereich "Überlebende" befanden.

Wie beim Minor GC wird die Anwendung während des Full GC gestoppt. Da die Stoppzeit lang ist, weil Alt enthalten ist, scheint es außerdem wichtig zu sein, das Auftreten zu unterdrücken, indem der Speicher im Bereich Jung so weit wie möglich verwendet wird.

Zusammenfassung

--Minor GC tritt auf, wenn der Eden-Bereich voll ist

Es stellte sich heraus, dass es ein Zyklus war.

Schließlich

Ich habe versucht, den grundlegenden Mechanismus von GC in Java zu organisieren. Ich war verwirrt über die Tatsache, dass es verschiedene Arten von JVMs gibt und was ich in jedem Artikel gesagt habe, etwas anders ist, aber ich beabsichtige, sie basierend auf den Quellen von Oracle und Open JDK zusammenzufassen. Nachdem der standardmäßig ausgewählte GC-Algorithmus G1GC ist, fasse ich ihn als Nächstes zusammen. Zuerst habe ich den zugrunde liegenden Mechanismus zur Speicherfreigabe eingeführt.

Referenz

Open JDK Document Oracle Document JAVAMAGAZINE / Open JDK und neuer Garbage Collector JVM GC-Algorithmus und Tuning

Recommended Posts

Organisieren Sie den Mechanismus von Java GC
Hinweise zu Java GC
Über die Entscheidungsbedingung der Java GC-Methode
Java-Referenzmechanismus (Stack und Heap)
Java
Java
Beginnen Sie mit der Funktionsweise von JVM GC
Konsoleneingabe in Java (Verständnis des Mechanismus)
[Java] Berechnungsmechanismus, Operatoren und Typkonvertierung