Heim  >  Artikel  >  Java  >  Was ist ein Haufen? Was ist der Methodenbereich? Einführung in den Heap- und Methodenbereich im JVM-Speichermodell

Was ist ein Haufen? Was ist der Methodenbereich? Einführung in den Heap- und Methodenbereich im JVM-Speichermodell

不言
不言Original
2018-09-15 17:43:0411941Durchsuche

Der Inhalt dieses Artikels befasst sich mit der Frage: Was ist ein Haufen? Was ist der Methodenbereich? Die Einführung des Heap- und Methodenbereichs im JVM-Speichermodell hat einen gewissen Referenzwert. Ich hoffe, dass es für Sie hilfreich ist.

1. Heap

1.1. Was ist ein Heap?

Der Heap ist ein Speicherbereich, der zum Speichern von Objekten verwendet wird. Daher ist es das Hauptziel der Garbage Collector (GC)-Verwaltung. Es weist folgende Merkmale auf:

  • Der Heap ist logisch in die „neue Generation“ und die „alte Generation“ unterteilt. Da die meisten Objekte in JAVA geboren und zerstört werden und eine kleine Anzahl lange Zeit im Speicher verbleiben kann, wird der Heap in die neue und die alte Generation unterteilt, um eine möglichst effektive Wiederverwertung dieser beiden Objekte zu erreichen Generation, und die Umsetzung ist anders. Verschiedene Garbage Collectors verfügen über unterschiedliche Recyclingmechanismen für diese beiden logischen Bereiche, die wir in den folgenden Kapiteln ausführlich erläutern werden.

  • Der vom Heap belegte Speicher erfordert keine physische Kontinuität, sondern nur logische Kontinuität.

  • Der Heap wird im Allgemeinen als erweiterbare Speichergröße implementiert. Verwenden Sie „-Xms“ und „-Xmx“, um den minimalen und maximalen Speicher des Heaps zu steuern und die Erweiterungsaktion durchzuführen durch die virtuelle Maschine. Da dieses Verhalten jedoch Leistung verbraucht, werden der maximale und minimale Speicher des Heaps im Allgemeinen gleich eingestellt.

  • Der Heap ist ein Speicherbereich, der von allen Threads gemeinsam genutzt wird, sodass jeder Thread dasselbe Objekt auf dem Heap erhalten kann.

  • Der Lebenszyklus des Heaps wird erstellt, wenn die virtuelle Maschine gestartet wird.

1.2. Heap-Ausnahme

Wenn der Heap keinen Objektspeicher zuweisen kann und nicht mehr erweitert werden kann, wird eine OutOfMemoryError-Ausnahme ausgelöst geworfen.

Im Allgemeinen wird eine GC durchgeführt, wenn der Heap keine Objekte zuordnen kann. Wenn das Objekt nach der GC immer noch nicht zugewiesen werden kann, wird ein Speichererschöpfungsfehler gemeldet. Diese Situation kann simuliert werden, indem kontinuierlich neue Objekte generiert werden, ohne Referenzen freizugeben:

/**
 * java堆溢出demo
 * JVM参数:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 * Created by chenjunyi on 2018/4/25.
 */
public class HeapOOM {

    static class OOMObject {
    }

    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<>();
        //不断创建新对象,使得Heap溢出
        while (true) {
            list.add(new OOMObject());
        }
    }

}

Im obigen Code werden Objekte kontinuierlich erstellt, ohne Referenzen freizugeben, was dazu führt, dass der GC den Heap-Speicher nicht zurückgewinnen kann eventuell OutOfMemoryError , Fehlermeldung:

java.lang.OutOfMemoryError: Java heap space

2. Methodenbereich

2.1. Was ist der Methodenbereich

Methodenbereich, auch Non-Heap (Non-Heap) genannt Heap), ein weiterer Speicherbereich, der von Threads gemeinsam genutzt wird. Es speichert hauptsächlich geladenen Klassenbytecode, Klassen-/Methoden-/Feld- und andere Metadatenobjekte, statische Endkonstanten, statische Variablen, vom JIT-Compiler kompilierten Code und andere Daten. Darüber hinaus enthält der Methodenbereich einen speziellen Bereich „Laufzeitkonstantenpool“, dessen Beziehung in der folgenden Abbildung dargestellt ist:

(1) Geladener Klassenbytecode: Um eine Klasse verwenden zu können, muss ihr Bytecode zunächst in den Speicher der JVM geladen werden. Die Quelle des Klassenbytecodes kann unterschiedlich sein, z. B. .class-Dateien, Netzwerkübertragung oder direkt vom cglib-Bytecode-Framework generiert.
(2) Metadatenobjekte wie Klasse/Methode/Feld: Nachdem der Bytecode geladen wurde, generiert die JVM basierend auf dem Inhalt Klasse/Methode/Feld und andere Objekte für diese Klasse. Sie werden zur Beschreibung einer Klasse verwendet. normalerweise in Es wird oft in der Reflexion verwendet. Im Gegensatz zu im Heap gespeicherten Java-Instanzobjekten werden diese beiden Objekte im Methodenbereich gespeichert.
(3) statisch-endgültige Konstanten und statische Variablen: Für diese beiden Arten von Klassenmitgliedern erstellt die JVM eine Kopie der Daten für sie im Methodenbereich, sodass nur eine Kopie der statisch geänderten Klassenmitglieder vorhanden ist die gleiche Klasse;
(4) Kompilierungsergebnisse des JIT-Compilers: Am Beispiel der virtuellen Hotspot-Maschine wird der JIT-Just-in-Time-Compiler verwendet, um den Hotspot-Code zur Laufzeit zu optimieren Kompilieren Sie den Bytecode in Maschinencode. Normalerweise verwendet die JVM die Methode „Interpretation und Ausführung“, um Bytecode auszuführen. Das heißt, wenn die JVM eine Bytecode-Anweisung liest, führt sie Stapeloperationen gemäß vorgegebenen Regeln aus und die Stapeloperationen werden weiter auf die zugrunde liegende Maschinenoperation abgebildet ; Nach der JIT-Kompilierung wird der ausgeführte Maschinencode direkt mit der zugrunde liegenden Maschine umgehen. Wie in der Abbildung unten gezeigt:

2.2. Laufzeitkonstantenpool

In Abschnitt 2.1 haben wir etwas über Klassen gelernt Der Bytecode wird beim Laden analysiert und verschiedene Dinge werden generiert und im Methodenbereich gespeichert. Der Bytecode einer Klasse enthält nicht nur Beschreibungsinformationen wie Klassenversion, Felder, Methoden, Schnittstellen usw., sondern auch einen Konstantenpool. Der Konstantenpool wird zum Speichern aller im Bytecode verwendeten Literale und Symbolreferenzen (z. B. Zeichenfolgenliterale) verwendet. Wenn die Klasse geladen wird, werden sie zur Speicherung in den Laufzeitkonstantenpool eingegeben.

Der Laufzeitkonstantenpool ist ein besonderer Teil des Methodenbereichs und dynamisch. Das heißt, zusätzlich zum Schreiben des Konstantenpools beim Laden der Klasse können auch währenddessen Konstanten hineingeschrieben werden die Ausführung des Java-Programms.:

rrree

2.3. Implementierung des Methodenbereichs

Die Implementierung des Methodenbereichs ist in der Spezifikation der virtuellen Maschine nicht klar festgelegt.

(1)HotSpot虚拟机1.7-:在JDK1.6及之前版本,HotSpot使用“永久代(permanent generation)”的概念作为实现,即将GC分代收集扩展至方法区。这种实现比较偷懒,可以不必为方法区编写专门的内存管理,但带来的后果是容易碰到内存溢出的问题(因为永久代有-XX:MaxPermSize的上限)。在JDK1.7+之后,HotSpot逐渐改变方法区的实现方式,如1.7版本移除了方法区中的字符串常量池。

(2)HotSpot虚拟机1.8+:1.8版本中移除了方法区并使用metaspace(元数据空间)作为替代实现。metaspace占用系统内存,也就是说,只要不碰触到系统内存上限,方法区会有足够的内存空间。但这不意味着我们不对方法区进行限制,如果方法区无限膨胀,最终会导致系统崩溃。

  我们思考一个问题,为什么使用“永久代”并将GC分代收集扩展至方法区这种实现方式不好,会导致OOM?首先要明白方法区的内存回收目标是什么,方法区存储了类的元数据信息和各种常量,它的内存回收目标理应当是对这些类型的卸载和常量的回收。但由于这些数据被类的实例引用,卸载条件变得复杂且严格,回收不当会导致堆中的类实例失去元数据信息和常量信息。因此,回收方法区内存不是一件简单高效的事情,往往GC在做无用功。另外随着应用规模的变大,各种框架的引入,尤其是使用了字节码生成技术的框架,会导致方法区内存占用越来越大,最终OOM。

2.4.方法区异常

  在2.3一节中,我们了解到方法区的2种实现方式最终都会有一个最大值上限,因此若方法区(含运行时常量池)占用内存到达其最大值,且无法再申请到内存时,便会抛出OutOfMemoryError。

  在下面的例子中,我们将使用cglib字节码生成框架不断生成新的类,最终使方法区内存占用满,抛出OutOfMemoryError:

/**
 * java方法区溢出OutOfMemoryError(JVM参数适用于JDK1.6之前,借助CGLIB)
 * JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M
 * Created by chenjunyi on 2018/4/26.
 */
public class JavaMethodAreaOOM {

    public static void main(String[] args) {
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> methodProxy.invokeSuper(objects, args));
            enhancer.create();
        }
    }

    static class OOMObject {
    }

}

报错信息为:

1 Caused by: java.lang.OutOfMemoryError: PermGen space
2   at java.lang.ClassLoader.defineClass1(Native Method)
3   ···

其实,在日常开发中,不仅仅使CGlib字节码生成框架会产生大量的class信息,动态语言、JSP、基于OSGI的应用都会在方法区额外产生大量的类信息。

Das obige ist der detaillierte Inhalt vonWas ist ein Haufen? Was ist der Methodenbereich? Einführung in den Heap- und Methodenbereich im JVM-Speichermodell. 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