java 中有几个难兄难弟,比如我昨天写的 java.lang.OutOfMemoryError: Java heap space 和今天要写的 java.lang.OutOfMemoryError: GC overhead limit exceeded 等。要搞清这些知识,就需要深入的理解 JVM 底层原理和实现机制。

那么我们今天就具体来说说 java.lang.OutOfMemoryError: GC overhead limit exceeded 吧!

我们都知道,Java 语言的一大优势就是内存管理,也就是垃圾回收机制。相比其他语言,如:C++等,它们这些语言中并没有自动内存回收机制, 需要程序员手工编写代码来进行内存分配和释放, 以重复利用堆内存。

也正是因为 Java 语言有自动垃圾回收机制,所以一些程序员在使用不当的情况下,会发生一系列你意想不到的 OutOfMemoryError。关于 OutOfMemoryError 错误,目前一共有 8 种,我们一一的来搞定它们!

java.lang.OutOfMemoryError: GC overhead limit exceeded 这种情况发生的原因是程序基本上耗尽了所有的可用内存, GC 也清理不了。

更准确的说法应该是:执行垃圾收集的时间比例太大,有效的运算量太小。默认情况下,如果GC花费的时间超过 98%,并且GC 回收的内存少于 2%,JVM 就会抛出这个错误。

java.lang.OutOfMemoryError: GC overhead limit exceeded 错误只在连续多次 GC 都只回收了不到2%的极端情况下才会抛出。假如不抛出 GC overhead limit 错误会发生什么情况呢? 那就是 GC 清理的这么点内存很快会再次填满,迫使 GC 再次执行。这样就形成恶性循环,CPU 使用率一直是 100%,而 GC 却没有任何成果。系统用户就会看到系统卡死。以前只需要几毫秒的操作,现在需要好几分钟才能完成。

下面我们来看一个产生“GC overhead limit exceeded” 错误的例子:

为了能够更快的看到效果,我们可以设置一下 JVM 的参数:

需要注意的是,不同的 GC 算法。产生的错误信息也不相同,有的可能会产生 java.lang.OutOfMemoryError: Java heap space 错误。

关于具体的 GC 算法,我给大家一张关于 Java8 GC 算法的列表,我后面再具体的写文章来讲。


我们在说说上面产生 OutOfMemoryError 错误的代码吧。Map 在进行 rehash 时抛出了 java.lang.OutOfMemoryError 错误消息。如果使用其他垃圾收集算法,比如 -XX:+UseConcMarkSweepGC,或者 -XX:+UseG1GC,错误将被默认的 exception handler 所捕获,但是没有 stacktrace 信息,因为在创建 Exception 时没办法填充 stacktrace 信息。

再比如,有些厂商的 JVM 在 Win7x64,Java8 环境配置如下 UseG1GC:

结果产生的错误信息却是:

上面这些真实的案例表明,在资源受限的情况下,无法准确预测程序会死于哪种具体的原因。所以在这类错误面前,不能绑死某种特定的错误处理顺序。

有的人在解决 “java.lang.OutOfMemoryError: GC overhead limit exceeded” 错误时,配置了下面的启动参数:

我告诉你,这是一种完全错误的做法。因为 UseGCOverheadLimit 这样使用并不能真正地解决问题,只能推迟一点 out of memory 错误发生的时间,到最后还得进行其他处理。指定这个选项,会将原来的 java.lang.OutOfMemoryError: GC overhead limit exceeded 错误掩盖,变成更常见的 java.lang.OutOfMemoryError: Java heap space 错误消息。

有时候触发 GC overhead limit 错误的原因, 是因为分配给JVM的堆内存不足。这种情况下只需要增加堆内存大小即可。

在大多数情况下, 增加堆内存并不能解决问题。例如程序中存在内存泄漏, 增加堆内存只能推迟产生 java.lang.OutOfMemoryError: Java heap space 错误的时间。

所以,要想从根本上解决问题,则需要排查内存分配相关的代码。简单来说,需要搞清楚一下两点:

  • 哪类对象占用了最多内存?

  • 这些对象是在哪部分代码中分配的?

解决这类问题的流程和我上篇文章《为什么会产生 java.lang.OutOfMemoryError: Java heap space 错误以及如何解决?》中提到的流程一致。我就不再啰嗦了!

©著作权归作者所有:来自51CTO博客作者mob604756f06ed8的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. Mysql错误代码
  2. PHP 共享内存使用场景及注意点
  3. Redis 内存为什么不宜过大
  4. 诊断虚拟机频繁 OOM 的问题
  5. 【Java内存溢出】系列(2/8):GC overhead limit exceeded
  6. 如何解决Dynamics 365的错误:用户身份验证无效,MSIS0006
  7. 一个Java对象究竟占用多大内存? --Java性能优化基础
  8. hive的join优化
  9. mysqldump备份数据库出现(Couldn't execute 'SHOW VARIABLES LIKE

随机推荐

  1. DELPHI10.2的LINUX数据库开发环境配置
  2. linux下安装 tomcat 和配置防火墙开放808
  3. CENTOS 修改MYSQL文件到内存盘
  4. linux查看磁盘使用情况命令
  5. Linux安装开发环境,必须配置的环节(Fedora1
  6. Linux操作以及c编程规范 、附带个问题
  7. Linux 的文件类型
  8. 第2章 计算机工作原理
  9. Linux中断(interrupt)子系统之三:中断流控处
  10. 我应该在哪里添加Yocto位烤任务来创建工