堆内存溢出
package com.dameng.lxm;
import java.util.ArrayList;
import java.util.List;
public class HeapOOM {
static class OOMObject {
}
public static void main(String[] args) {
List<OOMObject> objlist= new ArrayList<OOMObject>();
while(true) {
objlist.add(new OOMObject());
}
}
}
内存参数设置: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid15424.hprof ...
Heap dump file created [30880108 bytes in 0.034 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.base/java.util.Arrays.copyOf(Arrays.java:3512)
at java.base/java.util.Arrays.copyOf(Arrays.java:3481)
at java.base/java.util.ArrayList.grow(ArrayList.java:237)
at java.base/java.util.ArrayList.grow(ArrayList.java:244)
at java.base/java.util.ArrayList.add(ArrayList.java:454)
at java.base/java.util.ArrayList.add(ArrayList.java:467)
at testOom/com.dameng.lxm.HeapOOM.main(HeapOOM.java:14)
虚拟机栈和本地方法栈溢出
在《Java虚拟机规范》中描述了两种异常:
- 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。
- 如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出 OutOfMemoryError异常。
案例一:减小虚拟机栈容量
package com.dameng.lxm;
public class JavaVMStackSOF {
private int stackLength=1;
public void stackLeak() {
stackLength++;
stackLeak();
}
public static void main(String[] args) {
JavaVMStackSOF oom = new JavaVMStackSOF();
try {
oom.stackLeak();
} catch (Exception e) {
System.out.print("stack length:" +oom.stackLength);
throw e;
}
}
}
内存参数设置:-Xxss128k
The Java thread stack size specified is too small. Specify at least 180k
-Xxss180k
Exception in thread "main" java.lang.StackOverflowError
at testOom/com.dameng.lxm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:7)
at testOom/com.dameng.lxm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8)
at testOom/com.dameng.lxm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8)
at testOom/com.dameng.lxm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8)
at testOom/com.dameng.lxm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8)
at testOom/com.dameng.lxm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8)
at testOom/com.dameng.lxm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8)
at testOom/com.dameng.lxm.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8)
案例二:增大栈帧
package com.dameng.lxm;
public class JavaVMStackSOFB {
private static int stackLength = 0;
public static void test() {
long unused1, unused2, unused3, unused4, unused5,
unused6, unused7, unused8, unused9, unused10,
unused11, unused12, unused13, unused14, unused15,
unused16, unused17, unused18, unused19, unused20,
unused21, unused22, unused23, unused24, unused25,
unused26, unused27, unused28, unused29, unused30,
unused31, unused32, unused33, unused34, unused35,
unused36, unused37, unused38, unused39, unused40,
unused41, unused42, unused43, unused44, unused45,
unused46, unused47, unused48, unused49, unused50,
unused51, unused52, unused53, unused54, unused55,
unused56, unused57, unused58, unused59, unused60,
unused61, unused62, unused63, unused64, unused65,
unused66, unused67, unused68, unused69, unused70,
unused71, unused72, unused73, unused74, unused75,
unused76, unused77, unused78, unused79, unused80,
unused81, unused82, unused83, unused84, unused85,
unused86, unused87, unused88, unused89, unused90,
unused91, unused92, unused93, unused94, unused95,
unused96, unused97, unused98, unused99, unused100;
stackLength ++;
test();
unused1 = unused2 = unused3 = unused4 = unused5 =
unused6 = unused7 = unused8 = unused9 = unused10 =
unused11 = unused12 = unused13 = unused14 = unused15 =
unused16 = unused17 = unused18 = unused19 = unused20 =
unused21 = unused22 = unused23 = unused24 = unused25 =
unused26 = unused27 = unused28 = unused29 = unused30 =
unused31 = unused32 = unused33 = unused34 = unused35 =
unused36 = unused37 = unused38 = unused39 = unused40 =
unused41 = unused42 = unused43 = unused44 = unused45 =
unused46 = unused47 = unused48 = unused49 = unused50 =
unused51 = unused52 = unused53 = unused54 = unused55 =
unused56 = unused57 = unused58 = unused59 = unused60 =
unused61 = unused62 = unused63 = unused64 = unused65 =
unused66 = unused67 = unused68 = unused69 = unused70 =
unused71 = unused72 = unused73 = unused74 = unused75 =
unused76 = unused77 = unused78 = unused79 = unused80 =
unused81 = unused82 = unused83 = unused84 = unused85 =
unused86 = unused87 = unused88 = unused89 = unused90 =
unused91 = unused92 = unused93 = unused94 = unused95 =
unused96 = unused97 = unused98 = unused99 = unused100 = 0;
}
public static void main(String[] args) {
try {
test();
}catch (Error e){
System.out.println("stack length:" + stackLength);
throw e;
}
}
}
-Xxss180k
stack length:87
Exception in thread "main" java.lang.StackOverflowError
at testOom/com.dameng.lxm.JavaVMStackSOFB.test(JavaVMStackSOFB.java:26)
at testOom/com.dameng.lxm.JavaVMStackSOFB.test(JavaVMStackSOFB.java:27)
at testOom/com.dameng.lxm.JavaVMStackSOFB.test(JavaVMStackSOFB.java:27)
at testOom/com.dameng.lxm.JavaVMStackSOFB.test(JavaVMStackSOFB.java:27)
at testOom/com.dameng.lxm.JavaVMStackSOFB.test(JavaVMStackSOFB.java:27)
at testOom/com.dameng.lxm.JavaVMStackSOFB.test(JavaVMStackSOFB.java:27)
at testOom/com.dameng.lxm.JavaVMStackSOFB.test(JavaVMStackSOFB.java:27)
案例三:创建线程导致内存溢出
package com.dameng.lxm;
public class JavaVMStackOOM {
private void dontStop() {
while (true) {
}
}
public void stackLeakByThread() {
while (true) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
thread.start();
}
}
public static void main(String[] args) throws Throwable {
JavaVMStackOOM oom = new JavaVMStackOOM();
oom.stackLeakByThread();
}
}
Exception in thread "main" java.lang.OutOfMemoryError: unable to create native thread
方法区和运行时常量池溢出
案例一:运行时常量池导致的内存溢出异常
package com.dameng.lxm;
import java.util.HashSet;
import java.util.Set;
public class RuntimeConstantPoolOOM {
public static void main(String[] args) {
// 使用Set保持着常量池引用,避免Full GC回收常量池行为
Set<String> set = new HashSet<String>();
// 在short范围内足以让6MB的PermSize产生OOM了
short i = 0;
while (true) {
set.add(String.valueOf(i++).intern());
}
}
}
内存参数设置:-XX:PermSize=6M -XX:MaxPermSize=6M
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
at java.lang.String.intern(Native Method)
at org.fenixsoft.oom.RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java: 18)
案例二:借助cglib使得方法区出现内存溢出异常
package com.dameng.lxm;
public class JavaMethodAreaOOM {
public static void main(String[] args) {
while (true) {
Enhancer 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 {
}
}
内存参数设置:-XX:PermSize=10M -XX:MaxPermSize=10M
Caused by: java.lang.OutOfMemoryError: PermGen space
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
... 8 more
本机直接内存溢出
package com.dameng.lxm;
import java.lang.reflect.Field;
public class DirectMemoryOOM {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) throws Exception {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
while (true) {
unsafe.allocateMemory(_1MB);
}
}
}
内存参数设置:-Xmx20M -XX:MaxDirectMemorySize=10M
Exception in thread "main" java.lang.OutOfMemoryError
at sun.misc.Unsafe.allocateMemory(Native Method)
at org.fenixsoft.oom.DMOOM.main(DMOOM.java:20)