Heim  >  Artikel  >  Java  >  Detaillierte Einführung in den Java-Speicherbereich und die Speicherüberlaufausnahme

Detaillierte Einführung in den Java-Speicherbereich und die Speicherüberlaufausnahme

零下一度
零下一度Original
2017-06-25 10:58:351427Durchsuche

Java-Speicherbereich und Speicherüberlaufausnahme

1. Laufzeitdatenbereich

 

 1. Programmzähler: Thread privat, Wird zum Speichern des Speicherorts der aktuell ausgeführten Anweisung verwendet

2. Java Virtual Machine Stack: Thread privat, beschreibt das Ausführungsmodell der Java-Methode. Beim Ausführen einer Methode wird ein Stapelrahmen zum Speichern lokaler Variablen und Basistypvariablen erstellt . Referenz und andere Informationen

3. Java-nativer Methodenstapel: privater Thread, der die von der virtuellen Maschine verwendeten nativen Methoden bereitstellt

4. Java-Heap: gemeinsam genutzter Thread, ist der Hauptarbeitsplatz von der Garbage Collector; Speicherobjektinstanzen usw.

5. Methodenbereich: Thread-Freigabe; Informationen zur Speicherklasse, Konstanten, statische Variablen usw.

  Laufzeitkonstanten: Speichern verschiedener Literale und Symbolreferenzen generiert während der Kompilierung

6. Direkter Speicher: Maschinenspeicher

2. Virtuelles Maschinenobjekt

1. Erstellung des Objekts

  • Überprüfen Sie zuerst, ob der Konstantenpool die Symbolreferenz dieser Klasse finden und prüfen kann, ob die Klasse geladen und initialisiert wurde. Andernfalls muss zuerst der Ladevorgang durchgeführt werden.

  • Speicher für das Objekt zuweisen : Berechnen Sie den Speicherplatz und extrahieren Sie ihn aus dem Heap. Teilen Sie einen kontinuierlichen oder diskontinuierlichen Bereich; verwenden Sie cas+failure retry, um Thread-Sicherheitsprobleme zu vermeiden (da Objekte sehr häufig erstellt werden, weiß ich nicht, ob der aktuelle Speicher zugewiesen wurde)

  • Initialisieren Sie den Speicherplatz: Initialisieren Sie den zugewiesenen Speicherplatz auf den Wert 0

  • Legen Sie grundlegende Informationen des Objekts fest: Metadaten, Hash-Code, GC usw .

  • Init-Initialisierung von Java ausführen:

2. Speicherlayout des Objekts

Objektheader: Speichert den Hash-Code , Sperrstatus usw. und Typzeiger des Objekts (die Klasse, auf die das Objekt zeigt) (Metadaten)

Instanzdaten: die tatsächlich vom Objekt gespeicherten Informationen

Ausrichtungsauffüllung: Auffüllung entspricht zu den Regeln

3. Zugriff auf die Positionierung des Objekts

Zugriff auf das Objekt. Durch die Referenzdaten auf dem Java-Stack wird ein Verweis auf das Objekt aufrechterhalten

Zugriff Methoden: Handle und Direktzugriff

 

Handle: Im Heap wird ein Handle-Pool verwaltet, und die Referenzpunkte auf das Handle enthalten die Adressinformationen der Objektinstanzdaten und Typdaten

Es ist einfach, die Instanzdaten im Handle zu verschieben, der Overhead ist groß und es gibt viele einmalige Zeigerpositionierungen

 

Direkt: Referenzpunkte direkt auf die Objektadresse

Schnelle Geschwindigkeit

3. Tatsächlicher Kampf OutofMemoryERROR

1 .java Heap-Überlauf

 Parameter: -Xms Heap-Mindestwert; -XX:+HeapDumpOnOutOfMemoryError Speicher-Snapshot-Analyse, wenn ein Überlauf auftritt

  Heap-Speicherobjekte: A Es kann eine große Anzahl von Objekten erstellt werden, um einen Heap-Überlauf zu erreichen: Heap-Speicherplatz

2. Stapelüberlauf

Die Stapeltiefe kann erreicht werden, indem die Stapeltiefe durch unendliche Rekursion erhöht oder eine große Anzahl von Threads erstellt wird

 3. Methodenbereich und konstanter Poolüberlauf
//递归来StackOverFlowerpublic class JavaVMStackSOF {private int stackLength = 1;public void stackLeak(){
        stackLength++;
        stackLeak();
    }public static void main(String[] args)throws Throwable{
        JavaVMStackSOF oom = new JavaVMStackSOF();try {
            oom.stackLeak();
        } catch(Throwable e){
            System.out.println("stack length:" + oom.stackLength);throw e;
        }
    }
}
 
Parameter

: -XX:PermSize Methodenbereichsgröße; -XX:MaxPermSize Maximum Größe des Methodenbereichs

  Vor JDK1.6 konnten Sie eine große Anzahl von Strings erstellen und die virtuelle Maschine kopierte die Objekte in den konstanten Pool

 

In 1.7 und höher ist dies nicht möglich, da die virtuelle Maschine den Verweis auf das Objekt nur dann speichert, wenn dieses Objekt zum ersten Mal im Konstantenpool erscheint

Überlauf des Methodenbereichs: Der Methodenbereich speichert Klasseninformationen und Überläufe, indem er eine große Anzahl dynamischer Klassen generiert. Beispielsweise generiert Spring tatsächlich Klassen über dynamische Proxys

public class JavaMethodAreaOOM{public static void main(String[]args){while(true){//创建大量的动态类,动态代理OOMObjectEnhancer enhancer=new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor(){public Object intercept(Object obj,Method method,Object[]args,MethodProxy proxy)throws Throwable{return proxy.invokeSuper(obj,args);
                }}
            );
            enhancer.create();
        }}static class OOMObject{
    }
}
String.intern() ist eine native Methode. Ihre Funktion ist: Wenn der String-Konstantenpool bereits einen String enthält, der diesem String-Objekt entspricht, geben Sie den String zurück, der diesen String im Pool darstellt Der in diesem String-Objekt enthaltene Konstantenpool gibt einen Verweis auf dieses String-Objekt zurück

JDK6 und früher: Der Methodenbereich (permanente Generation) ist separat und der Konstantenpool befindet sich im Methodenbereich

JDK7: Zur permanenten Generation gehen

Wenn dieser Code in JDK 1.6 ausgeführt wird, erhält er zwei falsche Werte, aber wenn er in JDK 1.7 ausgeführt wird, erhält er einen wahren und einen falschen Wert.

Der Grund für den Unterschied ist: In JDK 1.6 kopiert die Methode intern () die erste gefundene Zeichenfolgeninstanz in die permanente Generation und gibt einen Verweis auf die Zeichenfolgeninstanz in der permanenten Generation und die Zeichenfolge zurück Die von StringBuilder erstellte Instanz befindet sich auf dem Java-Heap, daher darf es sich nicht um dieselbe Referenz handeln, und es wird „false“ zurückgegeben.

Und JDK 1.7: Die Implementierung von intern() kopiert die Instanz nicht mehr, sondern zeichnet nur die Instanzreferenz des ersten Vorkommens von im Konstantenpool auf, sodass die von intern() zurückgegebene Referenz die ist identisch mit der von StringBuilder erstellten Zeichenfolgeninstanz.

Der Vergleich von str2 gibt false zurück, da die Zeichenfolge „java“ bereits vor der Ausführung von StringBuilder.toString() angezeigt wurde und im Zeichenfolgenkonstantenpool bereits ein Verweis darauf vorhanden ist, der die Anforderungen von nicht erfüllt Prinzip „erstes Vorkommen“ und die Zeichenfolge „Computersoftware“ erscheint zum ersten Mal, daher wird „true“ zurückgegeben

 

Hinweis: 1.7 und höher speichern den Verweis, der zum ersten Mal angezeigt wird Analyse

4. Nativer Direktspeicher

Parameter: -XX: MaxDirectMemorySize Direktspeichergröße; Standard == maximaler Heapspeicher

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung in den Java-Speicherbereich und die Speicherüberlaufausnahme. 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