前言
看本文之前,可以先了解下什么是异常
12-异常
一、StackOverflowError
栈溢出,其他关于栈的介绍,可以参考 1-JVM体系结构概述
直接上代码看
public class Test02 {
public static void main(String[] args) {
System.out.println("sssss");
fun1();
System.out.println("uuuuuu");
}
public static void fun1(){
fun1();
}
}
// Exception in thread "main" java.lang.StackOverflowError
以上代码递归调用自己,最终导致栈溢出,这是error级别错误,不是Exception
二、OutOfMemoryError: Java heap space
new一个大对象导致堆内存溢出
堆占用太多也会触发GC,参考 4-制造GC/Full GC
public class Test01 {
public static void main(String[] args) throws InterruptedException {
byte[] bytes = new byte[10 * 1024 * 1024];
}
}
抛出异常
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at Demo03.Test01.main(Test01.java:17)
三、OutOfMemoryError: GC overhead limit
综上所述,用了98%的时间去GC却只回收了2%的堆内存,连续多次GC都只回收不到2%的内存的 极端情况下,会报错 GC overhead limit。
代码示例如下,数次GC,但是每次GC回收的内存小于2%,就会报错。
先使用如下配置,调小自己的堆大小
-Xms1m -Xmx2m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
/**
* @description: 模拟 java.lang.OutOfMemoryError: GC overhead limit exceeded
* -Xms10m -Xmx20m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
* MaxDirectMemorySize:直接内存大小,因为本机内存太大,所以设置的小一点
*
* @Author: wangchao
* @Date: 2021/7/31
*/
public class GCOverheadDemo {
public static void main(String[] args) {
int i = 0;
ArrayList<Object> list = new ArrayList<>();
try {
while (true){
// TODO 记得关注 https://www.runoob.com/java/java-string-intern.html
list.add(String.valueOf(++i).intern());
}
}catch (Throwable e){
System.out.println("***************i:"+i);
e.printStackTrace();
throw e;
}
}
}
// 输出
java.lang.OutOfMemoryError: GC overhead limit exceeded
四、OutOfMemoryError: Direct buffer memory
// -Xms10m -Xmx20m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
public class DirectBufferMemoryDemo {
public static void main(String[] args) {
// 默认是本机的1/4 ,为了测试,我们将直接内存调小 -XX:MaxDirectMemorySize=5m
System.out.println("配置的maxDirectMemory:"+(VM.maxDirectMemory()/(double)1024/1024)+"MB");
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
}
}
五、OutOfMemoryError: unable to create new native thread
public class UnableCreateNewThreadDemo {
public static void main(String[] args) {
for (int i = 0; i < 10000; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "start");
try {
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "" + i).start();
}
}
}
报错:
Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:717)
at com.supkingx.base.l_jvm.gc.oom.UnableCreateNewThreadDemo.main(UnableCreateNewThreadDemo.java:18)
六、OutOfMemoryError: Metaspace
// -XX:MetaspaceSize=5m -XX:MaxMetaspaceSize=20m
public class MetaspaceOOMDemo {
static class OOMTest {
}
public static void main(String[] args) {
int i = 0;
try {
while (true) {
i++;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMTest.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o, objects);
}
});
Object o = enhancer.create();
System.out.println("创建类:" + o);
}
} catch (Throwable e) {
System.out.println("多少次后发生了异常:" + i);
e.printStackTrace();
}
}
}
报错
Caused by: java.lang.OutOfMemoryError: Metaspace
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
... 14 more
报错原因如下
即 使用Enhancer创建数个代理类挤爆了MetaSpace