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