Heim  >  Artikel  >  Java  >  Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Java后端技术全栈
Java后端技术全栈nach vorne
2023-08-15 17:16:461186Durchsuche

Lassen Sie uns heute mit Ihnen über das Thema JVM-Speicherplatz sprechen. Diese Frage wird auch häufig in Interviews bei erstklassigen Internetunternehmen gestellt. Es wird empfohlen, dass Freunde sie häufig sammeln und lesen, wobei der Schwerpunkt auf dem Verständnis liegt. Okay, nicht mehr reden, kommen wir heute zum Hauptthema.

Die JVM unterteilt den Speicher in verschiedene Datenbereiche. Wo werden also die geladenen Klassen zugewiesen?

Das Bild unten zeigt verschiedene Speicherbereiche, darunter: Methodenbereich, Heap, Stapel virtueller Maschinen, lokaler Methodenstapel und Programmzähler.

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Methodenbereich

Der Methodenbereich wird zum Speichern von Daten wie Klasseninformationen, Konstanten, statischen Variablen, vom Just-in-Time-Compiler kompiliertem Code usw. verwendet, die geladen wurden durch die virtuelle Maschine. Die fünf Phasen des Klassenladens werden im Abschnitt Laden von Klassen erwähnt. In der Ladephase wird die durch den Bytestream dargestellte statische Speicherstruktur in die Laufzeitdatenstruktur des Methodenbereichs umgewandelt. In der Vorbereitungsphase wird der gesamte von den Variablen verwendete Speicher im Methodenbereich zugewiesen.

Programmzähler

Kommen Sie zu einem einfachen Code, berechnen Sie (1+2)*3 und geben Sie

public int cal() {
    int a = 1;
    int b = 2;
    int c = 3;
    return (a + b) * c;
}

zurück. Wenn dieser Code in die virtuelle Maschine geladen wird, werden die folgenden Bytes angezeigt Führt den Code aus, wird er Zeile für Zeile ausgeführt.

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Java ist multithreaded. Nachdem der Thread zurückgeschaltet hat, muss er wissen, wo sich die ursprüngliche Ausführungsposition befindet. Der Programmzähler wird verwendet, um diese Ausführungsposition aufzuzeichnen. Um sicherzustellen, dass sich die Zähler zwischen Threads nicht gegenseitig beeinflussen, ist dieser Speicherbereich für den Thread privat.

虚拟机栈

虚拟机栈也是线程私有的,生命周期与线程相同。每个线程都有自己的虚拟机栈,如果这个线程执行了一个方法,就会创建一个栈帧,方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。比如下面的例子,fun1调用fun2,fun2调用fun3,fun3创建Hello对象。

public void fun1() {
    fun2();
}

public void fun2() {
    fun3();
}

public void fun3() {
    Hello hello = new Hello();
}

调用的时候,流程图如下:

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

执行完成的时候,流程图如下:

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

每一个栈帧都包括了局部变量表、操作数栈、动态连接、方法返回地址和一些额外的附加信息。局部变量主要是存放方法参数以及方法内部定义的局部变量,操作数栈是一个后入先出栈,当方法刚刚开始执行的时候,这个方法的操作数栈是空的,在方法的执行过程中,会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈/入栈操作。

我们通过上面(1+2)*3的例子,把方法区、程序计数器、虚拟机栈的协同工作理一下。首先通过javap查看它的字节码,经过类加载器加载后,此时这个字节码存在方法区中。stack表示栈深度是2,locals是本地变量的slot个数,args_size是入参的个数,默认是this。栈的深度、本地变量个数,入参个数,都是在编译器决定的。

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

如下图,指令的位置是方法区,局部变量和操作数栈的位置是虚拟机栈,程序计数器就在程序计数器(这个下面的图就不再重复)。当执行偏地址为0的指令的时候,程序计数器为0,局部变量第一个值是this,当前的指令就是方法区0:iconst_1,指令iconst_1就是把int常量值1进栈,这个1就到了虚拟机栈的操作数栈中。

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

当执行偏地址为1的指令的时候,程序计数器为1,把操作数栈的值赋值到局部变量,此时操作数栈清空了,局部变量多了一个1,这条指令执行完,就是对应上面int a=1的语句。

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Zudem entsprechen die Zuordnungen der beiden Aussagen b und c den Anweisungen 2, 3, 4 und 5, die hier nicht wiederholt werden. Nach der Ausführung von 5, wie in der folgenden Abbildung gezeigt:

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Bei der Ausführung von 6 wird iload_1 ausgeführt, was bedeutet, dass die zweite lokale Variable vom Typ int an die Spitze des Stapels verschoben wird. Die Variable hier ist 1.

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Beim Ausführen von 7 wird iload_2 ausgeführt, was bedeutet, dass die dritte lokale Variable vom Typ int an die Spitze des Stapels verschoben wird. Die Variable hier ist 2.

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Bei der Ausführung von 8 handelt es sich um die iadd-Anweisung. Dies bedeutet, dass die beiden int-Typ-Elemente oben im Stapel aus dem Stapel herausgenommen und nach dem Ergebnis auf die Oberseite des Stapels geschoben werden erhalten.

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Weisen Sie beim Ausführen von 9 das Element 3 oben im Stapel der fünften lokalen Variablen zu.

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Wenn die Ausführung 11 erreicht, wird der Wert der fünften lokalen Variablen an die Spitze des Stapels verschoben. Wenn die Ausführung 13 erreicht, wird der Wert der vierten lokalen Variablen an die Spitze des Stapels verschoben 14: Die beiden Werte oben auf dem Stapel werden vom Stapel entfernt und das multiplizierte Ergebnis wird auf den Stapel verschoben. Wenn 15 ausgeführt wird, wird das Element vom Typ int oben auf dem Stapel abgelegt Der aktuelle Stapel wird von der aktuellen Methode zurückgegeben. Diese sind fast identisch mit den oben genannten, daher werde ich nicht auf Details eingehen.

Heap

Der einzige Zweck des Heap-Speicherbereichs besteht darin, Objektinstanzen zu speichern, und fast alle Objektinstanzen weisen hier Speicher zu. Beispielsweise ruft fun1 oben fun2 auf, fun2 ruft fun3 auf und fun3 erstellt ein Hello-Objekt. Wenn das Objekt in der fun3-Methode erstellt wird, wird es im Heap erstellt und die Adresse wird der lokalen Variablen von fun3 zugewiesen. Der Java-Heap kann auch unterteilt werden in: neue Generation und alte Generation; die neue Generation ist auch in Eden-Raum, From Survivor-Raum und To Survivor-Raum unterteilt.

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Zusammenfassung

Der Gesamtprozess ist wie folgt: Kompilieren Sie zunächst die Java-Datei in eine Klassendatei und laden Sie sie über den Klassenlader in den Methodenbereich. Wenn ein Thread eine Methode aufruft, erstellt er einen Stapelrahmen, liest den Bytecode im Methodenbereich und führt die Anweisung aus. Wenn die Anweisung ausgeführt wird, wird sie im Programmzähler aufgezeichnet wird im Heap-Speicher erstellt. Nachdem die Methode ausgeführt wurde, wird der Stapelrahmen gelöscht.

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Zugehörige Parameter

-XX: PermSize: Speicherkapazität der permanenten Generation.

-XX:MaxPermSize: Maximale Speicherkapazität der permanenten Generation.

-XX:MetaspaceSize: Die Größe des Anfangswerts des Metaspace

-XX:MaxMetaspaceSize: Die maximale Größe des Metaspace

-XX:CompressedClassSpaceSize: Die Speicherplatzgröße zum Speichern des Klass-Klassen-Metadatenteils im Metaspace

-Xss: Stapelspeicherkapazität.

-Xms: Heap-Speicherkapazität.

-Xmx: Die maximale Speicherkapazität des Heaps, normalerweise identisch mit der Einstellung -Xms, um die Auswirkungen einer Laufzeiterweiterung zu verhindern.

-Xmn: Speicherkapazität der neuen Generation, die alte Generation ist die Heap-Speicherkapazität - Speicherkapazität der neuen Generation

-XX: SurvivorRatio=8: Die neue Generation ist außerdem in Eden-Raum, From Survivor-Raum und To Survivor-Raum unterteilt , auf 8 gesetzt. Stellt den Eden-Raum dar: Vom Survivor-Raum: Zum Survivor-Raum = 8:1:1. Wenn die neue Generation beispielsweise 10 MB hat, dann belegt der Eden-Raum 8 MB und der From Survivor-Bereich und der To Survivor-Bereich jeweils 1 MB.

Fallerklärung JVM-Speicherplatz (empfohlene Sammlung)

Das obige ist der detaillierte Inhalt vonFallerklärung JVM-Speicherplatz (empfohlene Sammlung). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:Java后端技术全栈. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen