关于JVM运行时数据区中各内存的Out Of Memory代码演示
1. 测试堆内存溢出
package OOM;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: Cool_Wu
* @Date: 2020-10-20 20:27
*/
/**
* 测试堆内存溢出:
* 1.调整堆内存参数 VM options:-Xms20M -Xmx20M
* 2.使用死循环不断地创建对象,通过List集合保持对象的引用,
* 保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象
* 运行结果:java.lang.OutOfMemoryError: Java heap space
*/
public class TestHeapOOM {
static class OOMObject{}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<>();
while (true){
list.add(new OOMObject());
}
}
}
2.测试栈内存溢出
package OOM;
/**
* @Author: Cool_Wu
* @Date: 2020-10-20 21:13
*/
/**
* 测试JVM栈内存溢出:
* 1.调整栈内存参数 VM options:-Xss128K
* 2.使用递归定义大量的本地变量,增加此方法栈帧中本地变量表的长度,导致栈内存泄漏
*
* 运行结果:Exception in thread "main" java.lang.StackOverflowError
*/
public class TestStackOOM1 {
private static int stackLength = 1;
public static void stackLeak(){
stackLength++;
stackLeak();
}
public static void main(String[] args) throws Throwable{
try {
stackLeak();
}catch (Throwable e) {
System.out.println("stackLength :" + stackLength);
throw e;
}
}
}
package OOM;
/**
* @Author: Cool_Wu
* @Date: 2020-10-20 22:05
*/
/**
1. 测试JVM栈内存溢出:(一个线程一个栈,栈内存设置越大,溢出越快)
2. 1.调整栈内存参数 VM options:-Xss2M
3. 2.通过死循环不断的创建线程,通过另一个死循环保持线程存活避免回收
4. 5. 运行结果:Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
*/
public class TestStackOOM2 {
public static void dontStop(){
while (true){}
}
public static void main(String[] args) {
while (true) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
thread.start();
}
}
}
3. 测试云空间内存溢出
package OOM;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @Author: Cool_Wu
* @Date: 2020-10-20 23:35
*/
/**
* 测试元空间内存溢出:
* 1.调整元空间参数值 VM options:-XX:MetaspaceSize=10M -XX:MaxMetaspaceSize=10M
* 2.使用死循环不断地创建CGLib动态代理的class
* 运行结果:Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
*/
public class TestMetaOOM {
static class OOMObject{}
public static void main(String[] args) {
while (true){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(objects,args);
}
});
enhancer.create();
}
}
}
4. 测试本地直接内存溢出
package OOM;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
/**
* @Author: Cool_Wu
* @Date: 2020-10-20 23:54
*/
/**
* 测试本地直接内存溢出:
* 1.调整直接内存参数值 VM options:-Xmx20M -XX:MaxDirectMemorySize=10M
* 2.使用死循环不断地通过unsafe.allocateMemory()方法向操作系统申请分配内存
*
* 运行结果:Exception in thread "main" java.lang.OutOfMemoryError
* at sun.misc.Unsafe.allocateMemory(Native Method)
*/
public class TestDirectMemoryOOM {
private static final int MB = 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(MB);
}
}
}