Heim  >  Artikel  >  Java  >  Einführung in die JVM-Grundlagen: Laufzeitdatenbereich

Einführung in die JVM-Grundlagen: Laufzeitdatenbereich

巴扎黑
巴扎黑Original
2017-07-21 16:46:33884Durchsuche

Ich glaube, dieses Bild sollte jedem bekannt sein, der Kontakt zu JVM hat. Man kann sagen, dass dies ist JVMDie erste Lektion für den Einstieg. Darunter "Heap" und "Virtual Machine Stack (Stapel) ist noch bekannter. Im Folgenden wird anhand dieses Bildes eine kurze Einführung in den Laufzeitdatenbereich von JVM gegeben.

Programmzähler (Programmzählerregister)

Das ist das Gleiche Als Computerbetrieb Der Programmzähler im System ist ähnlich. Im Computerbetriebssystem stellt der Programmzähler die Adresse der nächsten von diesem Prozess auszuführenden Anweisung dar. Für JVM kann als die vom aktuellen Thread ausgeführte Adresse angesehen werden. Jeder Thread verfügt über einen Programmzähler (dies ist leicht zu verstehen, jeder Thread führt Aufgaben aus. Wenn der Thread gewechselt wird, muss er wiederhergestellt werden können an die richtige Position), der wichtige Punkt ist ——Programmzähler, dies ist der einzige in der JVM-Spezifikation, der dies nicht angibt Dies führt zu einem OutOfMemory (Speicherleck, im Folgenden als OOM bezeichnet) Bereich . Mit anderen Worten: Die verbleibenden 4 Bereiche im obigen Bild können OOM verursachen.

☆Virtual Machine Stacks (Java Virtual Machine Stacks)

Dieser Speicherbereich ist das, was wir oft verwenden Sagte Stack , wir wissen gut, dass es zum Speichern von Variablen verwendet wird, das heißt zum Beispiel:

int i = 0;

Der Stapelspeicher der virtuellen Maschine verwendet 4 Bytes, um die Variable i zu speichern . Der Speicherplatz für Variablen kann von Anfang an bestimmt werden (für Referenzvariablen wird natürlich eine Adressreferenz gespeichert, und seine Größe ist ebenfalls festgelegt), sodass dieser Speicherbereich vom Compiler bestimmt werden kann. Dieser Bereich wird StackOverflowError oder OOM Fehler. Legen Sie die JVM-Parameter "-Xss228k" fest (Stapelgröße ist 228k).

 1 package com.jvm; 2  3 /** 4  * -Xss228k,虚拟机栈大小为228k 5  * Created by yulinfeng on 7/11/17. 6  */ 7 public class Test { 8     private static int count = 0; 9 10     public static void main(String[] args) {11         Test test = new Test();12         test.test();13     }14 15     /**16      * 递归调用17      */18     private void test() {19         try {20             count++;21             test();22         } catch (Throwable e) {     //Exception已经捕获不了JVM抛出的StackOverflowError23             System.out.println("递归调用次数" + count);24             e.printStackTrace();25         }26     }27 }

Dies ist eine Rekursion ohne Beendigungsbedingungen. Das Ausführungsergebnis ist wie in der Abbildung unten dargestellt. StackOverflowError gibt die Stapeltiefe an Vom Thread angefordert. Größer als die von JVM zulässige Tiefe.

Für Single-Threaded-Situationen wird StackOverflowError

trotzdem ausgelöst. Wenn eine OOM-Ausnahme ausgelöst wird, liegt die Ursache darin, dass Threads kontinuierlich erstellt werden, bis der Speicher erschöpft ist. Der Speicher von JVM besteht aus Heap-Speicher

+ Methodenbereichsspeicher + verbleibend Speicher, das heißt der verbleibende Speicher =Der vom Betriebssystem der JVM zugewiesene Speicher - Heap-Speicher - Methodenbereichsspeicher. -Xss legt die Stapelkapazität jedes Threads fest, d. h. die Anzahl der Threads, die erstellt werden können = verbleibender Speicher / Stapelspeicher. Wenn zu diesem Zeitpunkt der Stapelspeicher größer ist, ist die Anzahl der erstellbaren Threads kleiner, und OOM tritt leicht auf, wenn der Stapelspeicher kleiner ist Die Anzahl der Threads, die erstellt werden können, wird größer sein und es wird nicht einfach sein. OOM erscheint. Der beste Weg, diese Situation zu vermeiden, besteht darin, den Heap-Speicher +

Methodenbereichsspeicher zu reduzieren oder den Stapelspeicher entsprechend zu reduzieren. Verwenden Sie für die Stapelspeicherkonfiguration im Allgemeinen den Standardwert 1M oder verwenden Sie das 64-Bit-Betriebssystem und 64 Teile von JVM.

Native Method Stack (

Native Method Stack)Native Method Stack Ähnlich wie beim Stapel der virtuellen Maschine besteht der Unterschied darin, dass der Stapel der virtuellen Maschine die Methode Java

bedient, während der Stapel der lokalen Methode die Methode Native bedient . In der HotSpot-Virtual-Machine-Implementierung werden der lokale Methodenstapel und der Virtual-Machine-Stack zu einem zusammengefasst. Ebenso wird auch StackOverflowError und OOM Ausnahmen.

Java Heap

  对于堆,Java程序员都知道对象实例以及数组内存都要在堆上分配。堆不再被线程所独有而是共享的一块区域,它的确是用来存放对象实例,也是垃圾回收GC的主要区域。实际上它还能细分为:新生代(Young Generation)、老年代(Old Generation)。对于新生代又分为Eden空间、From Survivor空间、To Survivor空间。至于为什么这么分,这涉及JVM的垃圾回收机制,在这里不做叙述。堆同样会抛出OOM异常,下面例子设置JVM参数” -Xms20M -Xmx20M(前者表示初始堆大小20M,后者表示最大堆大小20M)。

 1 package com.jvm; 2  3 import java.util.ArrayList; 4 import java.util.List; 5  6 /** 7  * -Xms20M -Xmx20M 堆初始大小20M 堆最大大小20M 8  * Created by yulinfeng on 7/11/17. 9  */10 public class Test {11 12     public static void main(String[] args) {13         List<Test> list = new ArrayList<Test>();14         int count = 0;15         try {16             while (true) {17                 count++;18                 list.add(new Test());   //不断创建线程19             }20         } catch (Throwable e) {21             System.out.println("创建实例个数:" + count);22             e.printStackTrace();23         }24 25     }26 }

  执行的结果可以清楚地看到堆上的内存空间溢出了。

方法区(Method Area

  对于JVM的方法区,可能听得最多的是另外一个说法——永久代(Permanent Generation),呼应堆的新生代和老年代。方法区和堆的划分是JVM规范的定义,而不同虚拟机有不同实现,对于Hotspot虚拟机来说,将方法区纳入GC管理范围,这样就不必单独管理方法区的内存,所以就有了永久代这么一说。方法区和操作系统进程的正文段(Text Segment)的作用非常类似,它存储的是已被虚拟机加载的类信息、常量(从JDK7开始已经移至堆内存中)、静态变量等数据。现设置JVM参数为-XX:MaxPermSize=20M(方法区最大内存为20M)。

 1 package com.jvm; 2  3 import java.util.ArrayList; 4 import java.util.List; 5  6 /** 7  * -XX:MaxPermSize=20M 方法区最大大小20M 8  * Created by yulinfeng on 7/11/17. 9  */10 public class Test {11 12     public static void main(String[] args) {13         List<String> list = new ArrayList<String>();14         int i = 0;15         while (true) {16             list.add(String.valueOf(i++).intern());   //不断创建线程17         }18     }19 }

 Tatsächlich sind für den obigen Code die Ergebnisse der Ausführung auf JDK6, JDK7, JDK8Alle sind unterschiedlich. Der Grund dafür ist, dass der String-Konstantenpool immer noch im Methodenbereich (permanente Generierung) in JDK6 gespeichert ist und daher OutOfMemoryError:Permanent Space ; und nach JDK7 wurde der String-Konstantenpool auf den Java-Heap verschoben, und der obige Code wird nicht angezeigt wirf OOM. Wenn der Heapspeicher auf 20M geändert wird, wird OutOfMemoryError:Java heap space ausgelöst ; Was JDK8 betrifft, wurde das Konzept des Methodenbereichs vollständig aufgehoben und durch Metaspace ( Metaspace)", also in JDK8 Parameter der virtuellen Maschine "-XX:MaxPermSize" hat keine Bedeutung. Es wird durch "-XX:MetaspaceSize" und " -XX ersetzt :MaxMetaspaceSize“ usw.

Das obige ist der detaillierte Inhalt vonEinführung in die JVM-Grundlagen: Laufzeitdatenbereich. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen 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