1. JVM-Speichermodelldiagramm
Der JVM-Laufzeitdatenbereich (JVM-Laufzeitbereich) bezieht sich tatsächlich auf die Aufteilung und Zuweisung des JVM-Speicherplatzes während der Ausführung der JVM. Zwei im Internet gefundene Bilder lauten wie folgt (ich persönlich denke, dass das zweite Bild des Native Method Stack im Java Thead-Modul gezeichnet werden sollte):
2. Einführung in jeden Datenbereich
1. Stapel Bereich
Der Stapel ist in Java Virtual Machine Stack und Local unterteilt Methodenstapel
Der entscheidende Punkt ist derJava Virtual Machine Stack, der Threadprivat ist und den gleichen Lebenszyklus wie der Thread hat.
Jede Methodenausführung erstellt einen Stapelrahmen , der zum Speichern der lokalen Variablentabelle, des Operationsstapels, des dynamischen Links und des Methodenausgangs verwendet wird , usw. . Jede Methode wird aufgerufen, bis sie ausgeführt wird. Entspricht dem Prozess eines Stapelrahmens vom Schieben in den Stapel bis zum Herausspringen aus dem Stapel in der virtuellen Maschine.
Der Stapel bezieht sich normalerweise auf den lokalen Variablentabellenteil, der die 8 grundlegenden Datentypen speichert, die während der Kompilierung bekannt sind, sowie Objektreferenzen und Befehlsadressen. Die lokale Variablentabelle wird während der Kompilierung zugewiesen. Bei der Eingabe einer Methode wird die für lokale Variablen in diesem Stapel zugewiesene Speichergröße bestimmt.
Es wird zwei Ausnahmen geben: StackOverFlowError und OutOfMemoneyError. Wenn die Tiefe des Thread-Anforderungsstapels größer ist als die von der virtuellen Maschine zugelassene Tiefe, wird ein StackOverFlowError-Fehler ausgegeben. Der Stapel der virtuellen Maschine wird dynamisch erweitert. Wenn die Erweiterung nicht für genügend Speicherplatz sorgen kann, wird ein OutOfMemoneyError ausgegeben.
Der lokale Methodenstapel bedient die von der virtuellen Maschine verwendeten lokalen Methoden (nativ) und ist außerdem Thread-privat .
2. Heap-Bereich
Der Heap ist ein von allen Threads gemeinsam genutzter Bereich und wird erstellt, wenn Die virtuelle Maschine startet, deren einziger Zweck darin besteht, Objektinstanzen zu speichern .
Der Heap-Bereich ist der Hauptbereich von gc. Er ist normalerweise in zwei Blöcke unterteilt, die junge Generation und die alte Generation. Genauer gesagt ist die junge Generation in den Eden-Bereich unterteilt, in dem neu erstellte Objekte gespeichert werden, und in den To-Survivor-Bereich, in dem die Objekte gespeichert werden, die den GC überlebt haben.
In vielen Artikeln wird jedoch eingeführt, dass es in drei Blöcke unterteilt ist und der Methodenbereich als permanente Generation gezählt wird. Dies basiert wahrscheinlich auf der Aufteilung virtueller Hotspot-Maschinen, und IBM j9 bietet beispielsweise keine Einführung in die permanente Generation. Unabhängig von der Partitionierung werden Objektinstanzen gespeichert.
Es wird eine Ausnahme OutOfMemoneyError geben
3. Methodenbereich
Der -Bereich wird von allen Threads gemeinsam genutzt und dient zum Speichern von Klasseninformationen, Konstanten, statischen Variablen und anderen Daten , die von der virtuellen Maschine geladen wurden . Wird von der Java Virtual Machine als logischer Teil des Heaps beschrieben. Es ist üblich, es auch die permanente Generation zu nennen
Die Müllabfuhr besucht diesen Bereich selten, aber er muss auch recycelt werden, hauptsächlich für das ständige Poolrecycling und die Typenentladung.
Der Konstantenpool wird zum Speichern verschiedener Bytecodes und Symbolreferenzen verwendet, die während der Kompilierungszeit generiert werden. Der Konstantenpool hat ein gewisses Maß an Dynamik . Während der Kompilierung generierte Konstanten können darin gespeichert werden. Konstanten können auch zur Laufzeit zum Konstantenpool hinzugefügt werden, z. B. die intern()-Methode von string.
4. Programmzähler
Die Zeilennummer, die vom Strom ausgeführt wird Thread-Indikator . Bestimmen Sie die nächste Anweisung, indem Sie den Wert des Zählers ändern, z. B. Schleifen, Verzweigungen, Sprünge, Ausnahmebehandlung, Thread-Wiederherstellung usw., die alle auf Zähler angewiesen sind, um abzuschließen.
Java Virtual Machine Multi-Threading wird durch abwechselndes Wechseln von Threads und Zuweisen von Prozessorausführungszeit implementiert. Damit der Threadwechsel an die richtige Position zurückkehrt, benötigt jeder Thread einen unabhängigen Programmzähler, ist also Thread-privat.
Die einzige Java Virtual Machine spezifiziert keinen OutofMemoryError-Block
3. Datenbereichszusammenfassung
Name |
Funktionen | Funktion |
Konfigurationsparameter |
Ausnahme |
Programmzähler |
Belegt wenig Speicher, Thread privat, Lebenszyklus ist der gleiche wie Thread |
Ungefähr Bytecode-Zeilennummernanzeige
|
Keine |
Keine |
Virtueller Maschinenstapel |
Thread privat, der Lebenszyklus ist der gleiche wie der Thread, Kontinuierlichen Speicherplatz verwenden |
Speichermodell für die Java-Methodenausführung, Speicherung lokaler Variablentabellen, Operationsstapel, dynamischer Links, Methodenexits und anderer Informationen
|
-Xss |
StackOverflowError
OutOfMemoryError
|
Java-Heap |
Thread-Sharing, der Lebenszyklus ist Genauso wie bei der virtuellen Maschine können Sie Objektinstanzen speichern, ohne aufeinanderfolgende Speicheradressen zu verwenden |
Alle Objektinstanzen (einschließlich Arrays) müssen auf dem Heap zugewiesen werden |
-Xms
-Xsx
-Xmn
|
OutOfMemoryError |
Methodenbereich |
Thread-Sharing, der Lebenszyklus ist der gleiche wie bei der virtuellen Maschine, Sie können keine kontinuierlichen Speicheradressen verwenden |
Speicherdaten wie Klasseninformationen, Konstanten, statische Variablen, vom Just-in-Time-Compiler kompilierter Code, der von der virtuellen Maschine geladen wurde
|
-XX:PermSize:16M
-XX:MaxPermSize:64M
|
OutOfMemoryError |
Laufzeitkonstantenpool
|
Teil des Methodenbereichs, dynamisch |
Speichern von Literalen und Symbolreferenzen |
|
|
4. Erweiterung: Direkter Speicher
Direkter Speicher (Direct Speicher) ist nicht Teil des Laufzeitdatenbereichs der virtuellen Maschine. Es handelt sich nicht um einen in der Java Virtual Machine-Spezifikation definierten Speicherbereich. Dieser Teil des Speichers wird jedoch ebenfalls häufig verwendet und kann auch OutOfMemoryError-Ausnahmen verursachen. Daher werden wir ihn hier erläutern.
Die NIO-Klasse (NewInput/Output) wurde JDK 1.4 neu hinzugefügt und eine auf Kanal und Puffer basierende E/A-Methode eingeführt, die direkt mithilfe der nativen Funktionsbibliothek Off-Heap-Speicher zugewiesen werden kann. und dann über ein DirectByteBuffer-Objekt arbeiten, das im Java-Heap als Referenz auf diesen Speicher gespeichert ist. Dies kann in einigen Szenarien die Leistung erheblich verbessern, da das Hin- und Herkopieren von Daten zwischen dem Java-Heap und dem nativen Heap vermieden wird.
5. Erweiterung: Vergleich von Heap und Stack
Manche Leute unterteilen den Java-Speicher oft in Heap-Speicher (Heap) und Stack-Speicher (Stack). Die Aufteilung ist tatsächlich weitaus komplizierter. Die Beliebtheit dieser Teilungsmethode zeigt nur, dass die Speicherbereiche, denen die meisten Programmierer am meisten Aufmerksamkeit schenken und die am engsten mit der Objektspeicherzuweisung zusammenhängen, diese beiden Bereiche sind.
Der Heap ist flexibel, aber nicht sicher. Für Objekte müssen wir sie dynamisch erstellen und zerstören. Wir können nicht sagen, dass die später erstellten Objekte nicht zerstört werden und die zuvor erstellten Objekte nicht zerstört werden können. In diesem Fall wird unser Programm schwierig auszuführen sein, daher wird der Heap verwendet um Objekte in Java zu speichern. Sobald das Objekt im Heap zerstört ist und wir weiterhin auf dieses Objekt verweisen, tritt die berühmte NullPointerException auf. Dies ist das Manko des Heaps – eine falsche Referenzlogik wird erst zur Laufzeit entdeckt.
Der Stapel ist nicht flexibel, aber streng, sicher und einfach zu verwalten. Denn solange die obere Referenz nicht zerstört wird, muss die untere Referenz noch vorhanden sein. In den meisten Programmen werden zuerst definierte Variablen und Referenzen auf den Stapel geschoben, und die später definierten Variablen werden gleichzeitig auf den Stapel geschoben und Referenzen innerhalb des Blocks werden im Eingangsbereich gespeichert, und wenn ein Block endet, wird er vom Stapel entfernt. Durch das Verständnis dieses Mechanismus können wir das Konzept des Gültigkeitsbereichs in verschiedenen Programmierungen leicht verstehen Gleichzeitig ist dies auch der Vorteil des Stapels – eine fehlerhafte Referenzlogik kann jederzeit entdeckt werden.
Stack – speichert hauptsächlich Referenzen und grundlegende Datentypen.
Heap – wird zum Speichern von Objektinstanzen verwendet, die von new erstellt wurden.
Referenz:
Das obige ist der detaillierte Inhalt vonGrafisches Beispiel für ein JVM-Speichermodell. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!