Heim  >  Artikel  >  Java  >  Detaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text)

Detaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text)

不言
不言nach vorne
2018-10-16 17:02:123615Durchsuche

Dieser Artikel bietet Ihnen eine detaillierte Erklärung (Bilder und Text) zum JVM-Speichermodell und zum Laufzeitdatenbereich. Ich hoffe, dass er für Sie hilfreich ist.

1. Java-Speichermodell

Detaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text)

Der Zweck des Java-definierenden Speichermodells ist: Maskiert die Unterschiede zwischen Speicherzugriffen für verschiedene Hardware und Betriebssysteme.

Das Java-Speichermodell schreibt vor, dass alle Variablen im Hauptspeicher gespeichert werden. Jeder Thread verfügt über einen eigenen Arbeitsspeicher.

Thread-Operationen für Variablen können nur im Arbeitsspeicher ausgeführt werden und können Variablen im Hauptspeicher nicht direkt lesen oder schreiben.

Der Variablenzugriff zwischen verschiedenen Threads muss über den Hauptspeicher erfolgen.

1. Die Beziehung zwischen dem Java-Speichermodell und dem Java-Laufzeitdatenbereich: Der Hauptspeicher entspricht dem Java-Heap und der Arbeitsspeicher entspricht dem Java-Stack.

2. Das Schlüsselwort volatile macht die Aktualisierungen von Variablen in jedem Arbeitsspeicher sichtbar. Es wird im Singleton-Modus von DCL verwendet

2. Java-Laufzeitdatenbereich/Speicherbereich

Da sich der Laufzeitdatenbereich von jvm verbessert hat, so Es wird Unterschiede zwischen verschiedenen JDK-Versionen geben.

1. Der JVM-Speicherbereich vor jdk1.7 hat eine permanente Generation

Detaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text)

1 Da die .java-Datei in eine .class-Datei kompiliert wird, dient der Zähler als Zeilennummernindikator für den vom aktuellen Thread ausgeführten Bytecode. Wenn der Bytecode-Interpreter funktioniert, wählt er den nächsten auszuführenden Bytecode-Befehl aus, indem er den Wert dieses Rechners ändert. Jeder Thread verfügt über einen unabhängigen Programmzähler.

2. Der lokale Methodenstapel ist der Stapel, der lokale native Methoden ausführt, die von virtuellen Maschinen implementiert werden.

3. Der Java Virtual Machine Stack beschreibt das Speichermodell, wenn der Thread die Java-Methode (Methode) ausführt. Jede Methode entspricht einem Stapelrahmen, und die lokale Variablentabelle im Stapelrahmen speichert die grundlegenden Datentypvariablen und Objektreferenzvariablen in der Methode.

Detaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text)

Wie in der Abbildung oben gezeigt, speichert die lokale Variablentabelle die 8 in der Methode deklarierten Basistypvariablen und Objektreferenzvariablen. Jeder Stapelrahmen verfügt außerdem über einen Verweis auf den Laufzeitkonstantenpool, der auf den String-Typ verweist. Hier ist eine klassische, durch String-Objekte generierte Interviewfrage!

4. Der Java-Heap ist der größte Speicherbereich in der JVM und wird von allen Threads gemeinsam genutzt. Fast alle Objektinstanzen werden hier zugeordnet, daher ist der Java-Heap auch der Hauptbereich für die JVM-Garbage Collection. Der Java-Heap ist in die junge Generation und die alte Generation unterteilt. Die junge Generation kann weiter in den Eden-Raum, den From Survivor-Raum und den To Survivor-Raum unterteilt werden.

Detaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text)

Wenn wir das Schlüsselwort new verwenden, um ein Objekt zuzuweisen, wird das Objekt im Java-Heap generiert.

Lassen Sie uns die Situation analysieren, wenn das Objekt generiert wird.

  1. Da Eden der größte ist, werden neu generierte Objekte dem Eden-Raum zugewiesen. Wenn der Eden-Raum fast voll ist, wird ein Minor GC durchgeführt und dann werden die überlebenden Objekte dorthin kopiert der From Survivor-Bereich. Zu diesem Zeitpunkt stellt der Eden-Raum weiterhin Heap-Speicher nach außen zur Verfügung.

  2. Die Objekte, die später generiert werden, werden immer noch im Eden-Raum platziert. Wenn der Eden-Raum wieder voll ist, werden der Eden-Raum und der From Survivor-Raum zu diesem Zeitpunkt ausgeführt Gleichzeitig wird ein kleinerer GC durchgeführt, und dann werden die überlebenden Objekte in den Bereich „To Survivor“ gestellt. Zu diesem Zeitpunkt stellt der Eden-Raum weiterhin Heap-Speicher nach außen zur Verfügung.

  3. Die nächste Situation steht im Einklang mit 2. Wenn der Eden-Raum fast voll ist, führen der Eden-Raum und der To Survivor-Raum einen Minor GC durch, und dann werden die überlebenden Objekte im From Survivor-Raum platziert.

  4. Die nächste Situation steht im Einklang mit 3. Wenn der Eden-Raum schnell oder langsam ist, führen der Eden-Raum und der From Survivor-Raum einen Minor GC durch, und dann werden die überlebenden Objekte im To Survivor-Raum platziert.

  5. bedeutet, dass einer der beiden Survivors zur Bereitstellung von Objektspeicher verwendet wird. Wenn der Eden-Raum und ein bestimmter Survivor-Raum GCed sind, kann der andere Survivor-Raum die Objekte, die den GC überlebt haben, nicht aufnehmen; andernfalls werden diese überlebenden Objekte in die alte Generation verschoben Raum.

  6. Wenn auch der Raum der alten Generation voll ist, wird ein Major GC durchgeführt, um den Raum der alten Generation zu recyceln. (Auch Full GC genannt, Full GC verbraucht viel Speicher und sollte vermieden werden)

Die junge Generation verwendet einen Kopieralgorithmus: Jedes Mal kopiert Minor GC die überlebenden Objekte im Eden-Bereich und einen Survivor-Bereich in einen anderen Survivor-Bereich. Die alte Generation verwendet einen Mark-Complement-Algorithmus: Jedes Mal, wenn Major GC die überlebenden Objekte an ein Ende des Speicherplatzes verschiebt, bereinigt er dann direkt den Speicher außerhalb der Endgrenze.

Große Objekte wie Arrays und sehr lange Zeichenfolgen gelangen direkt in den Raum der alten Generation.

5. Der Methodenbereich wird zum Speichern von Klasseninformationen, endgültigen Konstanten, statischen Variablen und anderen von der JVM geladenen Daten verwendet. Der Methodenbereich enthält auch einen Laufzeitkonstantenpool, in dem hauptsächlich Literale und Symbolreferenzen gespeichert werden, die während der Kompilierung generiert werden (platziert nach dem Laden der Klasse). Das Literal des String-Objekts wird in den Laufzeitkonstantenpool eingefügt.

Die Garbage Collection im Methodenbereich umfasst hauptsächlich das Recycling von Konstanten und das Entladen von Typen.

2. Im JVM-Speicherbereich von jdk1.8 und höher ersetzt Metaspace die permanente Generation

Detaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text)

Die Eigenschaften von Metaspace und permanenter Generierung sind gleich. Sie sind beide Implementierungen des JVM-Methodenbereichs und haben die gleiche Funktion. Der größte Unterschied zwischen Metaspace und permanenter Generierung besteht jedoch darin, dass sich Metaspace nicht im JVM-Speicher der virtuellen Maschine befindet, sondern lokalen Speicher verwendet.

Warum Metaspace statt permanenter Generierung verwenden?

  1. Strings werden in der permanenten Generation gespeichert und sind anfällig für Leistungsprobleme und Speicherüberläufe.

  2. Es ist schwierig, die Größe der Klassen- und Methodeninformationen zu bestimmen, daher ist es schwierig, die Größe der permanenten Generation anzugeben. Wenn sie zu klein ist, führt dies leicht zu permanenten Informationen Generationsüberlauf, und wenn er zu groß ist, kann es leicht zu einem Überlauf der alten Generation kommen.

  3. Die permanente Generation bringt unnötige Komplexität in den GC und die Recyclingeffizienz ist gering.

Direkter Speicher

NIO wurde hinzugefügt, nachdem JDK1.4 IO basierend auf Kanalkanälen und Pufferpuffern eingeführt hatte und native Funktionen direkt außerhalb des Heaps zuordnete Der Speicher verbessert die E/A-Leistung erheblich und vermeidet das Hin- und Herkopieren von Daten zwischen dem Java-Heap und dem naiven Heap durch das ursprüngliche BIO.

Detaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text)

3. Speicherzuweisung beim Generieren von String

Referenzartikel: Detaillierte Erklärung des Strings konstanter Pool in Java.

4. Speichersituation beim Generieren von Objekten

Lassen Sie uns unsere gängigen Speichermodelle zum Generieren von Objekten oder grundlegenden Datentypvariablen analysieren. Dadurch erhalten Sie ein besseres Verständnis der JVM.

int i =3;, eine Methode entspricht einem Stapelrahmen, und die grundlegenden Datentypvariablen in der Methode werden direkt im Stapelrahmen zugewiesen. Wenn es sich um einen statischen oder endgültigen Basisdatentyp handelt, wird er genau wie String im Laufzeitkonstantenpool gespeichert.

Object o1 = new Object();, die Objektreferenz (Object o1) wird im Stapelrahmen gespeichert, aber die Objektdaten (new Object()) werden im Java-Heap und der Objekttyp gespeichert Daten (Klasse und andere Informationen) werden im Methodenbereich gespeichert.

String s1 = new String("abcd"); unter Verwendung des mit new deklarierten Objekts wird die Objektreferenz (String s1) im Stapelrahmen gespeichert und die Objektdaten (new String("abcd" )) wird in Java gespeichert. Im Heap wird der Zeichenfolgenwert („abcd“) im Laufzeitkonstantenpool gespeichert.

String s2 = „abc“, die Objektreferenz (String s2) wird im Stapelrahmen gespeichert und der String-Wert („abc“) wird im Laufzeitkonstantenpool gespeichert.

Detaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text)

Die Beziehung zwischen dem Java-Stack, dem Java-Heap und dem Methodenbereich ist ungefähr wie in der obigen Analyse dargestellt.

3. Verschiedene Ausnahmeanalysen

1. Java-Heap-Speicherüberlauffehler OutOfMemoryError

Wenn der Java-Heap dort zugewiesen ist Es gibt zu viele Objekte und der Speicherplatz reicht nach dem GC immer noch nicht aus. Der folgende Test wird durchgeführt, indem zyklisch Objekte generiert werden, die Speicherplatz verbrauchen.

Zugehörige Anweisungen: VM Args: -Xms20m -Xmx40m, was darauf hinweist, dass der von der JVM zugewiesene Heap-Speicher mindestens 20 MB und der maximale Heap-Speicher 40 MB beträgt.

 public static void main(String[] args) {
   while (true) {
     List<object> list = new ArrayList(10);
     list.add(new Object());
   }
 }</object>

2. Java-Stack-Stapelüberlauffehler StackoverflowError

Wenn die Stapeltiefe des Java-Stacks größer als die von der JVM zulässige Tiefe ist, wird dieser Fehler ausgegeben . Das Folgende ist ein Stapeltest durch unendliche rekursive Aufrufe.

Verwandte Anweisungen: VM Args: -Xss128k, was darauf hinweist, dass die von der JVM zugewiesene Stapelkapazität 128 KB beträgt.

public class StackOOM {
    
    private int length = 1;
    
    public void stackLeak() {
        length++;
        stackLeak();
    }
    
    public static void main(String[] args) {
        StackOOM stackOOM = new StackOOM();
        stackOOM.stackLeak();
    }
}

Detaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text)


Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des JVM-Speichermodells und des Laufzeitdatenbereichs (Bild und Text). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen