This article simulates the actual memory overflow exception through several pieces of code.
The code in this article is based on the Oracle company's hotspot virtual machine.
1. Java Heap Overflow 1.1 simulation scenario
The Java heap is used to store objects, as long as the objects are constantly created, and the GC roots to the object to avoid the garbage collection mechanism from clearing these objects.
Then a memory overflow exception occurs when the number of objects reaches the capacity limit of the maximum heap.
Packagecom.lindaxuan.outofmemory;Importjava.util.ArrayList;Importjava.util.List;/*** VM Args:-xms20m-xmx20m-xx:+heapdumponoutofmemoryerror * Set the minimum-xms parameter of the heap to the maximum value-XMX parameter to avoid automatic heap scaling. * @authorLinxuan*/ Public classHeapoom {Static classOomobject {} Public Static voidMain (string[] args) {List<OOMObject> list =NewArraylist<oomobject>(); while(true) {List.add (Newoomobject ()); } }}/*Result:java.lang.OutOfMemoryError:Java heap spacedumping heap to java_pid9220.hprof ... Heap dump file created [27717826 bytes in 0.160 secs]exception in thread "main" Java.lang.OutOfMemoryError:Java Heap Spac E at Java.util.Arrays.copyOf (arrays.java:2245) at Java.util.Arrays.copyOf (arrays.java:2219) at JAVA.UTIL.ARRAYLIST.G Row (arraylist.java:242) at java.util.ArrayList.ensureExplicitCapacity (arraylist.java:216) at Java.util.ArrayList.ensureCapacityInternal (arraylist.java:208) at Java.util.ArrayList.add (arraylist.java:440) at Com.lindaxuan.outofmemory.HeapOOM.main (heapoom.java:19) at Sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method) at Sun.reflect.NativeMethodAccessorImpl.invoke (nativemethodaccessorimpl.java:57) at Sun.reflect.DelegatingMethodAccessorImpl.invoke (delegatingmethodaccessorimpl.java:43) at Java.lang.reflect.Method.invoke (method.java:606) at Com.intellij.rt.execution.application.AppMain.main ( appmain.java:144)*/1.2 Analyzing a heap snapshot with the Memory Impact analysis tool
2. Virtual machine stack and local method stack Overflow
The virtual machine stack and the local method stack are not distinguished in the hotspot virtual machine. The stack capacity is set with the-XSS parameter. Two types of exceptions are described in the Java Virtual Machine specification:
- If the thread requests a stack depth greater than the maximum allowable depth of the virtual machine lock, the Stackoverflowerror exception is thrown.
- Throws a OutOfMemoryError exception if the virtual machine cannot request enough memory space on the scale stack.
2.1 Stackoverflowerror Anomalies
Packagecom.lindaxuan.outofmemory;/*** VM args:-xss128k * error:could not create the Java Virtual machine. ERROR:A Fatal exception has occurred. Program would exit. The stack size specified is too small, specify at least 160k VM args:-xss256k *@authorLinxuan*/ Public classjavavmstacksof {Private intStacklength = 1; Public voidStackleak () {stacklength++; Stackleak (); } Public Static voidMain (string[] args)throwsthrowable {javavmstacksof oom=Newjavavmstacksof (); Try{oom.stackleak (); } Catch(Throwable e) {System.out.println ("Stack Length:" +oom.stacklength); Throwe; } }}/*result:stack length:1868exception in thread "main" java.lang.StackOverflowError at Com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak (javavmstacksof.java:18) at Com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak (javavmstacksof.java:19) at Com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak (javavmstacksof.java:19) at Com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak (javavmstacksof.java:19) at Com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak (javavmstacksof.java:19) at Com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak (javavmstacksof.java:19) at Com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak (javavmstacksof.java:19) at Com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak (javavmstacksof.java:19) at Com.lindaxuan.outofmemory.JavaVMStackSOF.stackLeak (javavmstacksof.java:19) ...*/
When a single thread, whether because the stack frame is too large or the virtual machine stack capacity is too small, when the memory is not allocated, the virtual machine throws a Stackoverflowerror exception.
2.2 OutOfMemoryError Anomalies
Packagecom.lindaxuan.outofmemory;/*** VM args:-xss2m (may be larger at this time) *@authorLinxuan*/ Public classJavavmstackoom {Private voidDontstop () { while(true) { } } Public voidStackleakbythread () { while(true) {thread thread=NewThread (NewRunnable () { Public voidrun () {dontstop (); } }); Thread.Start (); } } Public Static voidMain (string[] args)throwsthrowable {javavmstackoom oom=NewJavavmstackoom (); Oom.stackleakbythread (); }}/*my result:run too long*/3. Method area and run constant pool overflow 3.1 run-time zone overflow
The following code requires a jdk1.6 simulation.
Packagecom.lindaxuan.outofmemory;Importjava.util.ArrayList;Importjava.util.List;/*** VM args:-xx:permsize=10m-xx:maxpermsize=10m *@authorZzm * Could not download jdk1.6 for MacOS*/ Public classRuntimeconstantpooloom { Public Static voidMain (string[] args) {//use list to keep constant pool references to avoid full GC recycle constant pool behaviorlist<string> list =NewArraylist<string>(); //The 10MB permsize is enough to generate oom in the integer range. inti = 0; while(true) {List.add (string.valueof (i++). Intern ()); } }}/*Result:run too long*/
String.intern () returns the referenced test
Packagecom.lindaxuan.outofmemory; Public classRuntimeConstantPoolOOM2 { Public Static voidMain (string[] args) {String str1=NewStringBuilder ("China"). Append ("Diaoyu DAO")). toString (); System.out.println (Str1.intern ()==str1); String str2=NewStringBuilder ("Ja"). Append ("va")). toString (); System.out.println (Str2.intern ()==str2); }}/*Result:truefalse*/
For the Jdk1.6,intern () method, the first encountered string instance is copied to the permanent generation, and the reference to the string instance in the permanent generation is returned.
While StringBuilder creates a string instance in the Java heap, it is necessarily not the same reference and will return false.
The Intern () implementation in jdk1.7 does not replicate the instance, only the instance reference that first appears in the constant pool, so the reference returned by intern () and the string instance created by Stringbuild are the same.
3.2 String Creation object and corresponding memory state
And look at another piece of code.
Public class Stringconstantpool { publicstaticvoid main (string[] args) { New StringBuilder ("China"). Append ("Diaoyu Island"). toString (); = = str1) ; New String ("Do not slay the dragon on the Heavens"); = = str2);} } /* */
"Chinese Diaoyu Island" and "no Dragon Slayer" are not present in the constant zone, then why is the output one true and the other false?
This involves the principle of creating a String object. Let's take a look at the code and memory.
New //// when a string creates an object, it puts the parameter "China" and "Diaoyu" in a constant pool
Memory State 1
// Str1.intern () Copy the str1 reference to the constant pool
Memory State 2
New // when a string creates an object, it puts the argument "no Dragon Slayer" into a constant pool
Memory State 3
// Str2.intern () first go to the constant pool to see there is no "leaning Heaven does not kill Dragon", has already.
Memory Status 4 (consistent with memory status 3)
3.3 Run-time method area overflow
The following section of code uses CGLIB to cause a memory overflow exception in the method area.
Packagecom.lindaxuan.outofmemory;ImportOrg.springframework.cglib.proxy.Enhancer;ImportOrg.springframework.cglib.proxy.MethodInterceptor;ImportOrg.springframework.cglib.proxy.MethodProxy;ImportJava.lang.reflect.Method;/*** VM Args:-xx:permsize=10m-xx:maxpermsize=10m *@authorLinxuan*/ Public classJavamethodareaoom { Public Static voidMain (string[] args) { while(true) {Enhancer enhancer=Newenhancer (); Enhancer.setsuperclass (oomobject.class); Enhancer.setusecache (false); Enhancer.setcallback (NewMethodinterceptor () { PublicObject Intercept (Object obj, Method method, object[] args, Methodproxy proxy)throwsThrowable {returnproxy.invokesuper (obj, args); } }); Enhancer.create (); } } Static classoomobject {}}/** result:exception in thread ' main ' Exception:java.lang.OutOfMemoryError thrown from the Uncaughtexceptionhandler I N Thread "main"*/4. Native Direct Memory Overflow
The directmemory capacity is specified by-xx:maxdirectmemorysize and, if not specified, the default is the same as the Java heap maximum (-xmx specified).
Packagecom.lindaxuan.outofmemory;ImportSun.misc.Unsafe;ImportJava.lang.reflect.Field;/*** VM args:-xmx20m-xx:maxdirectmemorysize=10m *@authorLinxuan*/ Public classDirectmemoryoom {Private Static Final int_1MB = 1024 * 1024; Public Static voidMain (string[] args)throwsException {Field Unsafefield= Unsafe.class. Getdeclaredfields () [0]; Unsafefield.setaccessible (true); unsafe unsafe= (Unsafe) unsafefield.get (NULL); while(true) {unsafe.allocatememory (_1MB); } }}
The above is a simulation of various types of memory overflow exceptions.
Note:
The code for this article is based on an in-depth understanding of Java Virtual Machine 2.4 Combat: OutOfMemoryError exception, slight adjustment.
The parameters of the virtual machine can be flexibly adjusted according to different machine performance.
5. JVM-related wikis and tools
Memory Analyzer Download
Borrow HSDB to explore runtime data for hotspot VMS
Java Anti-compilation tool JAVAP
Java Fundamentals and Tools
Java Virtual Machine Architecture
Several scenarios of Java memory overflow