Detaillierte Erläuterung des Speichermodells der JVM-Serie

Detaillierte Erläuterung des Speichermodells der JVM-Serie

1. Speichermodell und Laufzeitdatenbereich

In diesem Kapitel wird das Speichermodell der Java Virtual Machine vorgestellt. Es ist klar, dass die JVM-Laufzeitdatenbank eine Spezifikation ist und das JVM-Speichermodell eine Implementierung dieser Spezifikation darstellt.

Der Schwerpunkt der Java Virtual Machine liegt auf der Speicherung von Daten im Heap- und Methodenbereich. Daher werden in diesem Kapitel auch diese beiden Aspekte ausführlich beschrieben. Der Heap und der Methodenbereich sind gemeinsam genutzter Speicher, während der Java Virtual Machine-Stack, der native Methodenstapel und der Programmzähler threadprivat sind.

2. Mindmaps und Legenden

Einer davon ist der Nicht-Heap-Bereich (Methodenbereich), der allgemein auch als „permanente Generation“ bezeichnet wird. Der andere ist der Heap-Bereich, der in den jungen Bereich und den alten Bereich unterteilt ist. Der junge Bereich ist in zwei Teile unterteilt, einer ist der Eden-Bereich und der andere ist der Survivor-Bereich (S0 + S1). Der S0-Bereich kann auch als From-Bereich bezeichnet werden, und S1 kann auch als To-Bereich bezeichnet werden.

3. Objekte beantragen Speicherplatz von JVM

4. Warum brauchen wir eine Survivor-Zone?

Warum brauchen wir einen Überlebensraum? Reicht Eden nicht aus?

Angenommen, der Survivor-Bereich ist nicht entworfen, wird im Eden-Bereich ein MinorGC ausgeführt und die Objekte werden direkt an den Old-Bereich gesendet. Auf diese Weise wird der Old-Bereich schnell aufgefüllt. Sobald der Old-Bereich voll ist, wird FullGC ausgeführt (der Old-Bereich führt MajorGC aus, normalerweise begleitet von MinorGC). FullGC ist sehr zeitaufwändig, daher besteht der Zweck des Entwurfs des Survivor-Bereichs darin, die Anzahl der an den Old-Bereich gesendeten Objekte zu verringern. Es gibt einen Übergangs-Survivor-Bereich.

Ergänzung: Minor GC: Neue Generation
Große GC: Alte Generation
Vollständige GC: Neue Generation + Alte Generation
Eden:S1:S2 ist 8:1:1

5. Warum brauchen wir zwei Überlebenszonen?

Der Zweck der Anforderung von zwei Survivor-Bereichen besteht darin, eine Speicherfragmentierung zu vermeiden. Warum sagst du das?
Angenommen, es wird nur ein Survivor-Space entworfen. Sobald der Eden-Space voll ist, wird Minor GC ausgeführt und die überlebenden Objekte im Eden-Space werden in den Survivor-Space verschoben. Das Problem tritt auf, wenn der Eden-Space das nächste Mal voll ist. Minor GC erzwingt, dass die Objekte im Eden-Space in den Survivor-Space verschoben werden, was dazu führt, dass der von den Objekten belegte Speicher nicht mehr vorhanden ist.

6. Beispiele zur Überprüfung

Heap-Speicherüberlauf

importiere lombok.Data;
importiere org.springframework.web.bind.annotation.GetMapping;
importiere org.springframework.web.bind.annotation.RestController;

importiere java.util.ArrayList;
importiere java.util.List;

@RestController
öffentliche Klasse HeapController {

    Liste<Foo> Liste = neue ArrayList<Foo>();
    @GetMapping(Wert = {"Heap"})
    öffentlicher String heapTest() {
        während (wahr) {
            Liste.Hinzufügen(neues Foo());
        }
    }


    @Daten
    Klasse Foo {
        Zeichenfolge str;
    }
}

Beim Zugriff auf die Schnittstelle kommt es zu einem Speicherüberlauf;

java.lang.OutOfMemoryError: Java-Heapspeicher

...

Sie können Parameter festlegen: zum Beispiel -Xms64M -Xmx512M

Überlauf des Methodenbereichsspeichers

Verwenden von ASM, Maven-Konfiguration:

<Abhängigkeit>
  <groupId>asm</groupId>
  <artifactId>asm</artifactId>
  <version>3.3.1</version>
</Abhängigkeit>

Schreiben Sie den Code und fügen Sie die Klasseninformationen zum Methodenbereich hinzu. Beachten Sie, dass Sie diesen Code nicht ausführen sollten, wenn die Leistung des Computers nicht ausreicht. Dies kann leicht zu einem Neustart des Computers führen. Wenn zu viel Speicher verbraucht wird, können Sie auch die Anzahl der Schleifen reduzieren.

importiere org.objectweb.asm.ClassWriter;
importiere org.objectweb.asm.MethodVisitor;
importiere org.objectweb.asm.Opcodes;

importiere java.util.ArrayList;
importiere java.util.List;

öffentliche Klasse MyMetaspace erweitert ClassLoader {

  öffentliche statische Liste<Klasse<?>> createClasses() {
    Liste<Klasse<?>> Klassen = neue ArrayList<Klasse<?>>();
    für (int i = 0; i < 10000000; ++i) {
      ClassWriter cw = neuer ClassWriter(0);
      cw.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "Klasse" + i, null,
              "java/lang/Object", null);
      MethodVisitor mw = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>",
              "()V", null, null);
      mw.visitVarInsn(Opcodes.ALOAD, 0);
      mw.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object",
              "<init>", "()V");
      mw.visitInsn(Opcodes.RETURN);
      mw.visitMaxs(1, 1);
      mw.visitEnd();
      MyMetaspace-Test = neuer MyMetaspace();
      byte[] code = cw.toByteArray();
      Klasse<?> Beispielklasse = test.defineClass("Klasse" + i, Code, 0,
              Codelänge);
      classes.add(Beispielklasse);
    }
    Rückgabeklassen;
  }
}

Methodenbereich Testschnittstelle:

importiere com.example.jvm.jvmexceptionexample.asm.MyMetaspace;
importiere org.springframework.web.bind.annotation.GetMapping;
importiere org.springframework.web.bind.annotation.RestController;

importiere java.util.ArrayList;
importiere java.util.List;

@RestController
öffentliche Klasse NonHeapController {

    Liste<Klasse<?>> Liste = neue ArrayList<Klasse<?>>();

    @GetMapping(Wert = {"/noheap"})
    öffentlicher String noheap() {
        während (wahr) {
            list.addAll(MeinMetaspace.createClasses());
        }
    }

}

java.lang.OutOfMemoryError: Metaspace

bei java.lang.ClassLoader.defineClass1 (native Methode) ~ [na:1.8.5_54]

Lösung: Legen Sie die Größe des Metaspace fest, zum Beispiel -XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=512M

Java Virtual Machine-Stapel

Wie wir bereits gelernt haben, wird der Java Virtual Machine-Stack in Form von Stack-Frames gespeichert. Eine Methode entspricht einem Stack-Frame, der in einem Warteschlangenmodus in den Stack geschoben wird. Wenn Sie also testen möchten, ob das Programm Probleme mit dem Java Virtual Machine-Stack verursacht, können Sie dies mit einer rekursiven Methode testen:

importiere org.springframework.web.bind.annotation.GetMapping;
importiere org.springframework.web.bind.annotation.RestController;

@RestController
öffentliche Klasse StackController {

    öffentliche statische lange Anzahl = 0;

    öffentliche statische Leere addieren (lang i) {
        zählen++;
        hinzufügen(i);
    }

    @GetMapping(Wert = {"Stapel"})
    öffentlicher void-Stapel () {
        hinzufügen(1);
    }

}

StackOverflow, Stapelüberlaufausnahme:

java.lang.StackOverflowError: null

bei com.example.jvm.jvmexceptionexample.controller.StackController.add(StackController.java:14) ~[Klassen/:na]

Lösung: Set -Xss256k: Legen Sie die Stapelgröße für jeden Thread fest. Nach JDK 5 beträgt die Stapelgröße jedes Threads 1 MB, davor betrug die Stapelgröße jedes Threads 256 K.

Oben finden Sie den detaillierten Inhalt der ausführlichen Erläuterung des Speichermodells der JVM-Reihe. Weitere Informationen zur Speicherstruktur des JVM-Speichermodells finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung des Unterschieds zwischen Java-Speichermodell und JVM-Laufzeitdatenbereich
  • Grafisches JVM-Speichermodell
  • Zusammenfassung der Wissenspunkte des JVM-Speichermodells
  • Ein Artikel, der Ihnen hilft, das JVM-Speichermodell zu verstehen

<<:  Tutorial zur Installation von mysql5.7.23 auf Ubuntu 18.04

>>:  Tutorial zum Erstellen eines Zookeeper-Servers unter Windows

Artikel empfehlen

So richten Sie eine automatische tägliche Datenbanksicherung in Linux ein

Dieser Artikel verwendet das Centos7.6-System und...

Implementierung des Vue 3.x-Projekts basierend auf Vite2.x

Erstellen eines Vue 3.x-Projekts npm init @vitejs...

Beispiel einer DOM-Operationstabelle (DOM erstellt Tabelle)

1. Erstellen Sie eine Tabelle mit HTML-Tags: Code...

Detailliertes Tutorial zur Neuinstallation von Python 3.6.6 auf CentOS 7.5

ps: Die Umgebung ist wie der Titel Mögliche Abhän...

Implementierungsmethoden gängiger CSS3-Animationen

1. Was ist CSS Animations ist ein vorgeschlagenes...

Detaillierte Erläuterung des Ausführungsprozesses der MySQL-Update-Anweisung

Es gab bereits einen Artikel über den Ausführungs...

Über die richtige Art und Weise der Zeitumrechnung in JS beim Excel-Import

Inhaltsverzeichnis 1. Grundlagen 2. Problembeschr...

Detaillierte Erläuterung der elastischen CSS3-Erweiterungsbox

verwenden Flexible Boxen spielen beim Front-End-L...

Führen Sie die Schritte zur Verwendung von mock.js im Vue-Projekt aus

Verwenden von mock.js im Vue-Projekt Auswahl des ...

Codeanalyse synchroner und asynchroner SetState-Probleme in React

React entstand als internes Projekt bei Facebook....

Detailliertes Tutorial zur Installation von Docker auf CentOS 8

1. Frühere Versionen yum entfernen Docker Docker-...

So entwickeln Sie Uniapp mit vscode

Da ich immer vscode zur Entwicklung von Front-End...

Universelle Lösung für den Fehler beim Starten von MySQL unter Windows

MySQL-Startfehler Vor der Installation von MySQL ...