Heim >Java >javaLernprogramm >Detaillierte Einführung in den Java-Speicherbereich und die Speicherüberlaufausnahme
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
Ü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:
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
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
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
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; } } }
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ückgegebenHinweis: 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 HeapspeicherDas 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!