Java内存溢出OOM
经典错误
JVM中常见的两个错误
StackoverFlowError :栈溢出
OutofMemoryError: java heap space:堆溢出
除此之外,还有以下的错误
- java.lang.StackOverflowError
- java.lang.OutOfMemoryError:java heap space
- java.lang.OutOfMemoryError:GC overhead limit exceeeded
- java.lang.OutOfMemoryError:Direct buffer memory
- java.lang.OutOfMemoryError:unable to create new native thread
- java.lang.OutOfMemoryError:Metaspace
架构
OutOfMemoryError和StackOverflowError是属于Error,不是Exception
StackoverFlowError
堆栈溢出,我们有最简单的一个递归调用,就会造成堆栈溢出,也就是深度的方法调用
栈一般是512K,不断的深度调用,直到栈被撑破
/**
* @author: 陌溪
* @create: 2020-03-24-14:42
*/
public class StackOverflowErrorDemo {
public static void main(String[] args) {
stackOverflowError();
}
/**
* 栈一般是512K,不断的深度调用,直到栈被撑破
* Exception in thread "main" java.lang.StackOverflowError
*/
private static void stackOverflowError() {
stackOverflowError();
}
}
运行结果
Exception in thread "main" java.lang.StackOverflowError
at com.moxi.interview.study.oom.StackOverflowErrorDemo.stackOverflowError(StackOverflowErrorDemo.java:17)
OutOfMemoryError
java heap space
创建了很多对象,导致堆空间不够存储
/**
* Java堆内存不足
* @author: 陌溪
* @create: 2020-03-24-14:50
*/
public class JavaHeapSpaceDemo {
public static void main(String[] args) {
// 堆空间的大小 -Xms10m -Xmx10m
// 创建一个 80M的字节数组
byte [] bytes = new byte[80 * 1024 * 1024];
}
}
我们创建一个80M的数组,会直接出现Java heap space
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
GC overhead limit exceeded
GC回收时间过长时会抛出OutOfMemoryError,过长的定义是,超过了98%的时间用来做GC,并且回收了不到2%的堆内存
连续多次GC都只回收了不到2%的极端情况下,才会抛出。假设不抛出GC overhead limit 错误会造成什么情况呢?
那就是GC清理的这点内存很快会再次被填满,迫使GC再次执行,这样就形成了恶性循环,CPU的使用率一直都是100%,而GC却没有任何成果。
代码演示:
为了更快的达到效果,我们首先需要设置JVM启动参数
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
这个异常出现的步骤就是,我们不断的像list中插入String对象,直到启动GC回收
/**
* GC 回收超时
* JVM参数配置: -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
* @author: 陌溪
* @create: 2020-03-24-15:14
*/
public class GCOverheadLimitDemo {
public static void main(String[] args) {
int i = 0;
List<String> list = new ArrayList<>(