一:Java堆溢出
VM参数:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
public class DumpOutOfMemory {
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<>();
while (true) {
list.add(new OOMObject());
}
}
}
运行结果:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid6828.hprof ...
Heap dump file created [28274507 bytes in 0.065 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
二:栈溢出:
栈溢出有两种异常:
1.线程请求的栈深度大于虚拟机所允许的栈深度,将抛出StackOverflowEorror异常。
2.如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemeryError异常。
StackOverflowEorror验证:
public class JavaVMStackSOF {
private int stackLength = 1;
public void stackLeak() {
stackLength++;
stackLeak();
}
public static void main(String[] args) {
new JavaVMStackSOF().stackLeak();
}
}
OutOfMemeryError验证:JVM参数:-Xss20m
public class JavaVMStackOOM {
private void dontStop() {
while (true) {
}
}
public void stackLeakByThread() {
while (true) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
thread.start();
}
}
public static void main(String[] args) {
new JavaVMStackOOM().stackLeakByThread();
}
}
三:方法区和运行时常量池溢出
JDK1.7 就开始“去永久代”的工作了。 1.7把字符串常量池从永久代中剥离出来,存放在堆空间中。
在java1.8中,元数据区取代了永久代。元空间与永久代之间最大的区别在于:元数据空间并不在虚拟机中,而是使用本地内存。
数据区和永久代本质上都是方法区的实现。方法区存放虚拟机加载的类信息,静态变量,常量等数据。
因此,不会出现永久带溢出的异常了。。。。
public class RunTimeConstantPoolOOM {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
int i = 0;
while (true) {
list.add(String.valueOf("aaaaaa" + i++).intern());
}
}
}
JVM参数:-Xms10m -Xmx10m -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=50m -XX:-UseGCOverheadLimit
输出:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:265)
public class JavMethodAreaOOM {
public static void main(String[] args) {
while (true) {
Enhancer enhance = new Enhancer();
enhance.setSuperclass(OOMObject.class);
enhance.setUseCache(false);
enhance.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> methodProxy.invokeSuper(o, objects));
enhance.create();
}
}
}
JVM参数:
-XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=50m
输出:
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:563)