Der Java Heap wird verwendet, um Objektinstanzen zu speichern. Wenn wir kontinuierlich Objekte erstellen und sicherstellen, dass zwischen GC Root und dem erstellten Objekt einen zugänglichen Pfad besteht, um zu vermeiden, dass das Objekt gesammelt wird, wird ein unzureichender Heap -Speicher verursacht, der eine Ausnahme von MemoryError erhöht.
/** * @Author Xiongyongshun * VM Args: Java -xms10m -xmx10m -xx:+heapdumponoutofMemoryError */public classOfMemoryErrortest {public static void main (String [] args) {list <intiere> list = new Arraylist <> (); int i = 0; while (true) {list.add (i ++); }}}Das obige ist ein Code, der eine Ausnahme von OutofMemoryError erhebt. Wir können sehen, dass das Objekt verhindert, dass Müll gesammelt wird, indem das Objekt ständig erstellt und speichert. Wenn es zu viele Objekte gibt, überflutet der Heap -Speicher.
Durch Java -xms10m -xmx10m -xx:+heapdumponoutofMemoryError setzen wir den Heap -Speicher auf 10 Megabyte und verwenden den Parameter -xx:+heapdumponoutofMemoryError, um die JVM -Ausdrucken der aktuellen Memory Snapshot zu erstellen.
Nach dem Kompilieren und Ausführen des oben genannten Codes ist die folgende Ausgabe:
>>> java -xms10m -xmx10m -xx:+heapdumponoutofMemoryError com.test.outofMemoryErrortest 16-10-02 23: 35java.lang.outofMemoryError: Java Heap SpaceTumping Heap zu Java_Pid1810.hprof- 0,125 Sekunden] Ausnahme im Thread "Haupt" java.lang.outofMemoryError: Java Heap Space bei Java.util.arrays.copyof (arrays.java:3210) bei java.util.arrays.copyof (Arrays.java:3181) at java.util.array. java.util.arrayList.ensureExplicitCapacity (arrayList.java:235) unter java.util.arrayList.ensureCapacityInternal (ArrayList.java:227) bei Java.util.ArrayList.add (ArrayList.java:458) at java.util.arraylist.add (ArrayList.java:458) at java.util.arrayList.add (Arraylist.java:458) at java.util.arraylist.add (ArrayList.java:458) at java.util. com.test.outofMemoryErrortest.main (outofMemoryErrortest.java:15)
Java Stackoverflowerror
Wir wissen, dass es einen Speicherbereich namens Virtual Machine Stack im Laufzeitbereich des JVM gibt. Die Funktion dieses Bereichs ist: Jede Methode erstellt bei Ausführung einen Stack -Frame, der zum Speichern von Informationen wie lokalen variablen Tabellen, Operand -Stapeln, Methodenausgängen usw. verwendet wird.
Daher können wir einen unendlich rekursiven rekursiven Aufruf erzeugen. Wenn die rekursive Tiefe zu groß ist, wird der Stapelraum erschöpft, was zu einer Ausnahme von Stackoverflowerror führt.
Hier ist der spezifische Code:
/** * @Author Xiongyongshun * VM Args: Java -xss64K */public classOfMemoryErrortest {public static void main (String [] args) {stackoutofMemoryError (1); } public static void stackoutofMemoryError (int tiefe) {tiefe ++; stackoutofMemoryError (Tiefe); }}Nach dem Kompilieren und Ausführen des oben genannten Codes werden die folgenden Ausnahmeinformationen ausgegeben:
Ausnahme im Thread "Haupt" java.lang.stackoverflowerror unter com.test.outofMemoryErrortest.stackoutofMemoryError (outofMemoryErrortest.java:27)
Speicherüberlauf im Methodenbereich
Beachten Sie, dass aufgrund von JDK8 die dauerhafte Generation entfernt und durch MetaPace in JDK8 ersetzt hat, keiner der folgenden zwei Beispiele verursacht java.lang.outofMemoryError: Permgen Space -Ausnahme.
Konstante Poolüberläufe während der Laufzeit
In Java 1.6 und früheren Versionen von Hotspot JVM gibt es ein Konzept der dauerhaften Generation, dh der Erzeugungssammlungsmechanismus von GC wird auf den Methodenbereich erweitert. Im Methodenbereich wird ein Teil des Speichers verwendet, um konstante Pools zu speichern. Wenn im Code zu viele Konstanten enthalten sind, wird der Speicher des konstanten Pools erschöpft, was zu einem Speicherüberlauf führt. Wie füge ich also eine große Anzahl von Konstanten zum konstanten Pool hinzu? Zu diesem Zeitpunkt müssen Sie sich auf die String.intern () -Methode verlassen. Die Funktion der String.Intern () -Methode lautet: Wenn der Wert dieser Zeichenfolge bereits im konstanten Pool vorhanden ist, gibt diese Methode die Referenz auf die entsprechende Zeichenfolge im konstanten Pool zurück. Fügen Sie ansonsten den in dieser Zeichenfolge enthaltenen Wert zum konstanten Pool hinzu und geben Sie die Referenz auf dieses String -Objekt zurück. In JDK 1.6 und früheren Versionen wird der konstante Pool in der dauerhaften Generation zugewiesen. Daher können wir die Größe des konstanten Pools indirekt einschränken, indem wir die Parameter "-xx: Permsize" und "-xx: maxpermSize" einstellen.
Beachten Sie, dass die oben erwähnte Speicherverteilung der oben genannten und konstanten Pool nur für JDK 1.6 und frühere Versionen beträgt. In JDK 1.7 oder höher ist das Speicherlayout geringfügig, da das Konzept der dauerhaften Erzeugung entfernt wird.
Das Folgende ist ein Beispiel für Code, um den Speicherüberlauf von konstanten Pools zu implementieren:
/** * @Author XiongyongShun * VM Args: -xx: permsize = 10m -xx: maxpermSize = 10m */public class runTimeConstantPooloomTest {public static void main (String [] args) {list <string> list = new Arraylist <string> (); int i = 0; while (true) {list.add (string.ValueOf (i ++). praktion ()); }}}Wir sehen, dass in diesem Beispiel die methode von String.intern () genau verwendet wird, um dem konstanten Pool eine große Anzahl von Stringkonstanten hinzuzufügen, was zum Speicherüberlauf des konstanten Pools führt.
Wir kompilieren und führen den obigen Code über JDK1.6 aus, und die folgende Ausgabe wird sein:
Ausnahme in Thread "Haupt" java.lang.outofMemoryError: Permgen -Raum bei java.lang.string.intern (native Methode) bei com.test.runtimeConstantpooloomTest.main (RunTimeConstantpooloomTest.java:16)
Es ist zu beachten, dass, wenn der obige Code zusammengestellt und durch JDK1.8 ausgeführt wird, die folgende Warnung vorliegt und keine Ausnahme generiert wird:
>>> Java -xx: permSize = 10m -xx: maxpermSize = 10m com.test.runtimeConstantpooloomTest 16-10-03 0: 23Java Hotspot (TM) 64-Bit-Server VM VM Warnung: Ignorieren Option permsize = 10m; Die Unterstützung wurde in 8,0 Java Hotspot (TM) 64-Bit-Server-VM-Warnung entfernt: Option maxperms = 10m; Die Unterstützung wurde in 8.0 entfernt
Speicherüberlauf im Methodenbereich
Die Funktion des Methodenbereichs besteht darin, die relevanten Informationen der Klasse wie Klassennamen, Klassenzugriffsmodifikatoren, Feldbeschreibungen, Methodenbeschreibungen usw. zu speichern.
// VM Argumente: -xx: permSize = 10m -xx: maxpermSize = 10mpublic class methodAreaoomTest {public static void main (String [] args) {while (true) {Enhancer Enhancer = new Enhancer (); Enhancer.SetsuperClass (MethodAreaoomTest.Class); Enhancer.SetUsecache (Falsch); Enhancer. Enhancer.create (); }}}Im obigen Code verwenden wir CGLIB, um eine große Anzahl von Klassen dynamisch zu generieren. In JDK6 generiert das Ausführen des oben genannten Codes eine Ausnahme von Permgen Space:
/System/library/frameworks/javavm.framework/versions/1.6/home/bin/java -jar -xx: permsize = 10m -xx: maxpermSize = 10m Ziel/test-1.0-snapshot.jar
Das Ausgabeergebnis ist wie folgt:
Verursacht durch: java.lang.outofMemoryError: Permgen -Raum bei java.lang.classloader.defineclass1 (native Methode) bei Java.lang.Classloader.DefineClassCond (Classloader.java:637) at java.lang.laSlader.Defineclasse (Classloader.
METASPACE -Speicherüberlauf
Im Abschnitt Überlauf des Speicherüberlaufs im Methodenbereich haben wir erwähnt, dass JDK8 kein Konzept der dauerhaften Generation hat, sodass diese beiden Beispiele den erwarteten Effekt nach JDK8 nicht erreicht haben. Gibt es in JDK8 Fehler wie Speicherüberlauf im Methodenbereich? Natürlich einige. In JDK8 wird der MetaPace -Bereich verwendet, um klassenbezogene Informationen zu speichern. Wenn MetaPace nicht ausreicht, wird eine Ausnahme von Java.lang.outofMemoryError: MetaSpace ausgeworfen.
Nehmen wir das oben erwähnte Beispiel als Beispiel:
// VM Argumente: -xx: maxmetaspaceSize = 10mpublic class methodAreaOoMTest {public static void main (String [] args) {while (true) {Enhancer Enhancer = new Enhancer (); Enhancer.SetsuperClass (MethodAreaoomTest.Class); Enhancer.SetUsecache (Falsch); Enhancer. Enhancer.create (); }}}Der Code -Teil dieses Beispiels wurde nicht geändert. Der einzige Unterschied besteht darin, dass wir JDK8 verwenden müssen, um diesen Code auszuführen, und den Parameter -xx: maxmetaspaceSize = 10m festlegen. Dieser Parameter zeigt dem JVM an, dass die maximale Größe von MetaPace 10 m beträgt.
Dann verwenden wir JDK8, um dieses Beispiel zu kompilieren und auszuführen und die folgende Ausnahme auszugeben:
>>> java -jar -xx: maxmetaspaceSize = 10m Ziel/test -1.0 -snapshot.jarexception In Thread "Haupt" java.lang.outofMemoryError: metaspace at net.sf.cglib.core.abractclasgenerator.generat (AbstractClassesGener.java:345) at net.sf.cglib.proxy.enhancer.generate (Enhancer.java:492) unter net.sf.cglib.core.abstractClassGenerator $ classloaderData.get (AbstractClassgenerator.java:114) unter net.sf.cglib.core.abstractClassGenerator.create (AbstractClassGenerator.java:291) bei net.sf.cglib.proxy.enhancer.createhelper (Enhancer.java:480) at net.sf.cglib.proxy.enhancer.enhancer.enhancer.enhancer.enhancer.enhancer.enhancer.enhancer.create.create (ärger. com.test.methodareaoomTest.main (MethodAreaoomTest.java:22)
Zusammenfassen
In dem oben genannten dreht sich alles um gemeinsame Ausnahmen von Speicherüberlauf und Code -Beispiele in diesem Artikel. Ich hoffe, es wird für alle hilfreich sein. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!