前言

看本文之前,可以先了解下什么是异常
12-异常

一、StackOverflowError

栈溢出,其他关于栈的介绍,可以参考 1-JVM体系结构概述
直接上代码看

  1. public class Test02 {
  2. public static void main(String[] args) {
  3. System.out.println("sssss");
  4. fun1();
  5. System.out.println("uuuuuu");
  6. }
  7. public static void fun1(){
  8. fun1();
  9. }
  10. }
  11. // Exception in thread "main" java.lang.StackOverflowError

以上代码递归调用自己,最终导致栈溢出,这是error级别错误,不是Exception

二、OutOfMemoryError: Java heap space

new一个大对象导致堆内存溢出
堆占用太多也会触发GC,参考 4-制造GC/Full GC

  1. public class Test01 {
  2. public static void main(String[] args) throws InterruptedException {
  3. byte[] bytes = new byte[10 * 1024 * 1024];
  4. }
  5. }
  6. 抛出异常
  7. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
  8. at Demo03.Test01.main(Test01.java:17)

三、OutOfMemoryError: GC overhead limit

image.png
综上所述,用了98%的时间去GC却只回收了2%的堆内存,连续多次GC都只回收不到2%的内存的 极端情况下,会报错 GC overhead limit。
代码示例如下,数次GC,但是每次GC回收的内存小于2%,就会报错。
先使用如下配置,调小自己的堆大小
-Xms1m -Xmx2m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m

  1. /**
  2. * @description: 模拟 java.lang.OutOfMemoryError: GC overhead limit exceeded
  3. * -Xms10m -Xmx20m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
  4. * MaxDirectMemorySize:直接内存大小,因为本机内存太大,所以设置的小一点
  5. *
  6. * @Author: wangchao
  7. * @Date: 2021/7/31
  8. */
  9. public class GCOverheadDemo {
  10. public static void main(String[] args) {
  11. int i = 0;
  12. ArrayList<Object> list = new ArrayList<>();
  13. try {
  14. while (true){
  15. // TODO 记得关注 https://www.runoob.com/java/java-string-intern.html
  16. list.add(String.valueOf(++i).intern());
  17. }
  18. }catch (Throwable e){
  19. System.out.println("***************i:"+i);
  20. e.printStackTrace();
  21. throw e;
  22. }
  23. }
  24. }
  25. // 输出
  26. java.lang.OutOfMemoryError: GC overhead limit exceeded

四、OutOfMemoryError: Direct buffer memory

  1. // -Xms10m -Xmx20m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
  2. public class DirectBufferMemoryDemo {
  3. public static void main(String[] args) {
  4. // 默认是本机的1/4 ,为了测试,我们将直接内存调小 -XX:MaxDirectMemorySize=5m
  5. System.out.println("配置的maxDirectMemory:"+(VM.maxDirectMemory()/(double)1024/1024)+"MB");
  6. ByteBuffer byteBuffer = ByteBuffer.allocateDirect(6 * 1024 * 1024);
  7. }
  8. }

异常原因如下
image.png

五、OutOfMemoryError: unable to create new native thread

  1. public class UnableCreateNewThreadDemo {
  2. public static void main(String[] args) {
  3. for (int i = 0; i < 10000; i++) {
  4. new Thread(() -> {
  5. System.out.println(Thread.currentThread().getName() + "start");
  6. try {
  7. Thread.sleep(Integer.MAX_VALUE);
  8. } catch (InterruptedException e) {
  9. e.printStackTrace();
  10. }
  11. }, "" + i).start();
  12. }
  13. }
  14. }
  15. 报错:
  16. Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread
  17. at java.lang.Thread.start0(Native Method)
  18. at java.lang.Thread.start(Thread.java:717)
  19. at com.supkingx.base.l_jvm.gc.oom.UnableCreateNewThreadDemo.main(UnableCreateNewThreadDemo.java:18)

出现错误原因如下
image.png

六、OutOfMemoryError: Metaspace

  1. // -XX:MetaspaceSize=5m -XX:MaxMetaspaceSize=20m
  2. public class MetaspaceOOMDemo {
  3. static class OOMTest {
  4. }
  5. public static void main(String[] args) {
  6. int i = 0;
  7. try {
  8. while (true) {
  9. i++;
  10. Enhancer enhancer = new Enhancer();
  11. enhancer.setSuperclass(OOMTest.class);
  12. enhancer.setUseCache(false);
  13. enhancer.setCallback(new MethodInterceptor() {
  14. @Override
  15. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  16. return methodProxy.invokeSuper(o, objects);
  17. }
  18. });
  19. Object o = enhancer.create();
  20. System.out.println("创建类:" + o);
  21. }
  22. } catch (Throwable e) {
  23. System.out.println("多少次后发生了异常:" + i);
  24. e.printStackTrace();
  25. }
  26. }
  27. }
  28. 报错
  29. Caused by: java.lang.OutOfMemoryError: Metaspace
  30. at java.lang.ClassLoader.defineClass1(Native Method)
  31. at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
  32. ... 14 more

报错原因如下
image.png
即 使用Enhancer创建数个代理类挤爆了MetaSpace