1.模拟出JVM Metaspace内存溢出的场景体验一下
Metaspace内存溢出根本原因:1.就是Metaspace内存设置太早 2.就是代码里面有大量生成了动态类。
一旦Metaspace区域满了,就会触发Full GC连带着回收Metaspace中的类,但是此时大量的类是不能被回收的。不能放下任何一个类,此时必然会触发Metaspace区域的内存溢出,导致JVM也是崩溃掉,无法继续运行了。
-
第一步在代码里面添加cglib的依赖
cglib
cglib
3.3.0
-
第二步编写创建动态类代码
public static void main(String[] args) {
int count = 0;
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MethodAreaOOM.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
return proxy.invoke(obj, args);
}
});
enhancer.create();
System.out.println(++count);
}
}
- 第三步修改Metaspace大小
-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m - 代码运行
运行一段时间后Caused by: java.lang.OutOfMemoryError: Metaspace。
这个OutOfMemoryError就是经典的内存溢出的问题,而明确告诉是Metaspace这块区域内存溢出了。
2.模拟出JVM栈内存溢出的场景体验一下
通常来说,我们会设置每个线程的栈内存就是1MB,假设你一个JVM进程内包括他自带的后台线程,你依赖的第三方组件的后台线程,加上你的核心工作线程(比如说你部署在Tomcat中,那就是Tomcat的工作线程),还有你自己可能额外创建的一些线程,可能你一共JVM中有1000个线程。那么1000个线程就需要1GB的栈内存空间,每个线程有1MB的空间。
所以Metaspace区域+堆内存+几百个线程的栈内存,就是JVM一共对机器上的内存资源的一个消耗。
-
编写代码
public static void main(String[] args) { doSome(); } private static void doSome() { doSome(); }
-
设置栈大小
-Xms5m -Xmx5m
-
运行代码
Exception in thread “main” java.lang.StackOverflowError
3.模拟出JVM堆内存溢出的场景体验一下
-
编写代码
public static void main(String[] args) { int count=0; List<Object> list=new ArrayList<>(); while (true){ list.add(new Object()); System.out.println("创建第"+(++count)+"个object"); } }
-
设置堆大小
-Xms10m -Xmx10m
结论:当前创建了第360145个对象堆内存实在放不下任何其他对象,此时就会OutOfMemory了,Exception in thread “main” java.lang.OutOfMemoryError: Java heap space