java.lang.OutOfMemoryError: GC overhead limit exceeded和Java heap space

120 阅读2分钟

准备工作

  • idea
  • 新建一个类,编辑类的启动参数
  • 添加以下jvm启动参数:-Xss128k -Xms5m -Xmx5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\apps
  • -Xss128k:设置每个线程的堆栈大小为128k,实验二会用到
  • -Xmx5m 设置JVM最大可用内存为5m -Xms5m 设置JVM初始内存为5m
  • -XX:+HeapDumpOnOutOfMemoryError 可以让虚拟机在出现内存溢出异常的时候Dump出当前的内存堆转储快照以便进行事后分析
  • -XX:HeapDumpPath=D:\apps 指定快照文件存储的位置

image.png

实验一:堆内存溢出

public static void main(String[] args) {  
  
    List<String> list = new ArrayList<>();  
    while (true) {  
        String s = new String("abckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkfsdjks");  
        list.add(s);  
    }  
}

实验一结果

image.png

实验二:堆内存溢出

public static void main(String[] args) {  
  
    List<String> list = new ArrayList<>();  
    while (true) {  
        String s = new String("abckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkfsdjks" + Math.random());  
        list.add(s);  
    }  
}

实验二结果

image.png

实验三

public static void main(String[] args) {  
    testStack(0);  
}  
  
private static int testStack(int num) {  
    return testStack(num + 1);  
}

实验三结果 栈溢出并不会生成二进制dump文件 image.png

可以看到实验一和实验二都生成了后缀名为hprof的Dump文件,有了这个文件,就可以使用MemoryAnalyzer等工具进行分析,排查问题。

MemoryAnalyzer下载地址:eclipse.dev/mat/downloa… 注意,最新版本要求jdk17以上

MemoryAnalyzer旧版本可以点此下载: eclipse.dev/mat/previou…

java.lang.OutOfMemoryError: GC overhead limit exceeded和Java heap space

java.lang.OutOfMemoryError: Java heap space (JVM 堆空间溢出)就是在创建新的对象时, 堆内存中的空间不足以存放新创建的对象,导致此种问题的发生。如果确认不是代码问题,可通过调整JVM启动参数-Xms5m -Xmx5m来解决。

java.lang.OutOfMemoryError: GC overhead limit exceeded:这个错误是由于JVM花费太长时间执行GC且只能回收很少的堆内存时抛出的。根据Oracle官方文档,默认情况下,如果Java进程花费98%以上的时间执行GC,并且每次只有不到2%的堆被恢复,则JVM抛出此错误。

image.png

除了这两种OutOfMemoryError异常之外,官方还定义了其它以下几种内存溢出类型:

  • java.lang.OutOfMemoryError: Java heap space
  • java.lang.OutOfMemoryError: GC Overhead limit exceeded
  • java.lang.OutOfMemoryError: Requested array size exceeds VM limit
  • java.lang.OutOfMemoryError: Metaspace
  • java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?
  • java.lang.OutOfMemoryError: Compressed class space
  • java.lang.OutOfMemoryError: reason stack_trace_with_native_method

更多的OutOfMemoryError细节可以参考Oracle官方文档 docs.oracle.com/javase/8/do…