1. JAVA堆溢出
1.1 设置idea JVM参数
image.png-Xmx30m -Xms20m -XX:+HeapDumpOnOutOfMemoryError
1.2 代码示例
代码如下:
import java.util.ArrayList;
import java.util.List;
public class HeapOOM {
static class OOMObject {}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<>();
while(true) {
list.add(new OOMObject());
}
}
}
image.png
1.3 内存映像分析工具
-
在idea中搜索插件“JProfiler”,安装完成,并重启idea,当出现如下图图标,则表示安装成功。
image.png
2. 栈溢出
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 (Throwable e) {
System.out.println("Stack length: " + oom.stackLength);
throw e;
}
}
}
配置Vm options参数:
-Xss128k
image.png
3. 方法区和运行时常量池溢出
3.1 运行时常量池溢出
jdk7前,运行时常量池放在老年代,JDK7以后放在堆中。
配置参数:
-Xmx6m
不提代码如下:
import java.util.HashSet;
import java.util.Set;
public class RuntimeConstantPoolOOM {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
short i = 0;
while(true) {
set.add(String.valueOf(i++).intern());
}
}
}
image.png
3.2 方法区内存溢出
方法区是一个逻辑概念,其具体实现为jdk1.8的元空间与jdk1.8之前的永久代,他们之间最大的区别在于:元空间并不在JVM管理的内存中,而是使用本地内存。
替代的原因
1、1.8之前,字符串存在永久代中,容易出现性能问题和内存溢出,只有fullGC才会扫描清理到永久代,效率偏低。字符串常量
2、类及方法的信息等比较难确定其大小,放入系统内存更为合适
JVM options配置参数如下:
-XX:MaxMetaspaceSize=20m
示例代码如下
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
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() {
@Override
public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(obj, args);
}
});
enhancer.create();
}
}
static class OOMObject {}
}
image.png
3.3 参数说明
-XX:MaxMetaspaceSize: 设置元空间最大值,默认为-1,即不限制,或者说只受限于本地内存大小。
-XX:MetaspaceSize: 指定元空间的初始空间大小,以字节为单位,达到该值就会触发垃圾收集进行类型卸载。
-XX:MinMetaspaceFreeRatio: 作用是在垃圾收集之后控制最小的元空间剩余容量的百分比,可减少因为元空间不足导致的垃圾收集的频率。
4. 本机直接内存溢出
可通过 -XX:MaxDirectMemorySize参数指定,如果不指定则它和JAVA堆最大值一致。
该区域内存溢出的明显特征是在Heap Dump文件中看不到明显异常,且Dump文件很小,程序中直接或间接使用了DirectMemory。
网友评论