一、常见JVM异常示例代码:
package com.houxr.jvm.study;
import com.google.common.collect.Lists;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/
jvm test
需要设置 VM options : -Xms1m -Xmx1m -XX:MaxMetaspaceSize=5M
https://blog.csdn.net/soonfly/article/details/70147205
@author houxiurong
@date 2018-11-01
/
public class JvmTest extends ClassLoader {
/
List是动态增长的,因此容量不够了,就会扩容,一旦空闲内存分配完毕,请求不到其他内存,就抛出OutOfMemoryError。
<p>
模拟OutOfMemoryError 堆溢出错误
java.lang.OutOfMemoryError: Java heap space
*/
public static void outOfMemoryError() {
ArrayList list = Lists.newArrayList();
while (true) {
list.add(new JvmTest());
}
}
/
不断往堆中塞新增的StringBuffer对象,堆满了就直接溢出了
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
*/
public static void heapOverFlow() {
int count = 10000;
int size = 0;
while (true) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < count; i++) {
buffer.append(i);
}
System.out.println("=======================" + (++size));
}
}
/
栈溢出错误
程序详解:
执行main函数会创建一个线程,同时创建一个虚拟机栈(栈内存)
调用JvmTest.stackOverflowError()时,会对 stackOverflowError()进行压栈操作,将 stackOverflowError()运行期数据的数据集
保存到栈帧(Stack Frame)(如果main方法里面调用多个方法,会执行多个压栈操作)。
stackOverflowError()递归调用时,都会产生一个新的栈帧区块,这时就会连续的产生新的栈帧区块
当栈内存超过系统配置的栈内存-Xss:2048,就会出现java.lang.StackOverflowError异常.这也是为什么对于需要谨慎使用递归调用的原因!
Stack length:11131
<p>
Exception in thread "main" java.lang.StackOverflowError
/
public void stackOverflowError() {
STACK_COUNT++;
stackOverflowError();
}
private Integer STACK_COUNT = 1;
/
运行时常量池导致内存溢出
JDK1.7 Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
JDK1.8 CMS Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
/
public static void runtimeConstantPoolOOM1() {
//List保持常量池引用,避免Full GC回收常量池行为
List<String> list = Lists.newArrayList();
int i = 0;
while (true) {
list.add(String.valueOf(i++).intern());
}
}
/*
运行时常量溢出-问题思考
String.intern()是一个Native方法,
作用是:如果字符串常量池中已经包含一个等于此String对象的字符串,
则返回代表池中这个字符串的String对象,否则,将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。
/
public static void runtimeConstantPoolOOM2() {
String str1 = new StringBuilder("土豆丝").append("不加辣").toString();
String str11 = "土豆丝不加辣";
//JDK 1.6 false JDK 1.7 true JDK 1.8 false
System.out.println("========str1======" + (str1.intern() == str1));
// JDK 1.8 true
System.out.println("========str11======" + (str1.intern().equals(str11)));
String str2 = new StringBuilder("ja").append("va").toString();
String str22 = str2.intern();
//JDK 1.6 false JDK 1.7 true JDK 1.8 false
System.out.println("========str2======" + (str2 == str22));
}
/
方法区溢出
<p>
MetaSpace 溢出
方法区的内存溢出 中, JDK8 没有了永久代的概念
在JDK8中,使用了MetaSpace的区域来存放Class的相关信息,
当 MetaSpace 内存空间不足时, 会抛出 java.lang.OutOfMemoryError: Metaspace异常.
$ -XX:MaxMetaspaceSize=5M
CGLIB直接操作字节码运行时,生成大量的动态类
*/
public static void jdk8MethodAreaOOM() {
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(JvmTest.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o, objects);
}
});
enhancer.create();
}
}
public static void main(String[] args) throws Throwable {
// 模拟OutOfMemoryError 堆溢出错误
// JvmTest.outOfMemoryError();
// JvmTest.heapOverFlow();
//栈溢出
JvmTest jvmTest = new JvmTest();
try {
jvmTest.stackOverflowError();
} catch (Throwable e) {
System.out.println("========Stack length:" + jvmTest.STACK_COUNT);
throw e;
}
// 运行时常量池导致内存溢出
// JvmTest.runtimeConstantPoolOOM1();
// JvmTest.runtimeConstantPoolOOM2();
//jvm 8 永久代去掉使用 MetaSpace
// JvmTest.jdk8MethodAreaOOM();
}
}
二、调试上面代码最好在IDEA或者Eclipse中设置如下参数,会有更好的效果。
-Xms5m -Xmx5m -XX:MetaspaceSize=5m -XX:MaxMetaspaceSize=5M -Xss256k -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintClassHistogram -XX:+HeapDumpOnOutOfMemoryError
本文作者:
侯秀荣
版权声明:
本文版权内容属于 [houxiurong.com] 转载请标明出处;本站提供的一切信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途。
评论一下?