java.lang.OutOfMemoryError:GC overhead limit exceeded

java.lang.OutOfMemoryError:GC overhead limit exceeded简单来说,java.lang.OutOfMemoryError:GCoverheadlimitexceeded发生的原因是,当前已经没有可用内存,经过多次GC之后仍然没能有效释放内存。

大家好,又见面了,我是你们的朋友全栈君。

你好,我是看山。

本文已被《从小工到专家的 Java 进阶之旅》收录。

java.lang.OutOfMemoryError这个错误是比较经典的错误了,经过JDK不断的迭代,服务器硬件的不断升级。。。总之,社会在发展,时代在进步。很多错误已经消失在时代的浪潮中。我也是很久没有见过这个错误了,以至于都以为在Java的世界中不会再碰到这个错误。结果,就在最疏忽的时候碰到了TA,真是,心中一万只神兽奔袭而过,狠狠的践踏了我这颗上了年纪的心脏啊。

吐槽完毕,言归正传。

Java刚刚出现的年代,有一个相比于其他语言的优势就是,内存回收机制。不需要明确的调用释放内存的API,java就自动完成,这个过程就是Garbage Collection,简称GC。这对以懒著称的程序猿们来说,绝对是重大利好。但是,凡事有利必有弊,可以肯定的是,Java语言是人创造的,GC也是人编写的代码,绝对不是机器自动完成的。也就是说,GC的过程是另外一群程序猿根据可能出现的情况,预设了GC条件,把符合回收条件的内存空间释放出来。一旦被占用的内存空间不符合释放的条件,GC没办法清理,那就会适时出现java.lang.OutOfMemoryError。这个错误就是提醒我们这群程序猿,写GC程序的程序猿不知道这种情况怎么处理,为了安全也不便处理,谁使用Java就自己看着解决吧。

说起来,java.lang.OutOfMemoryError有几种分类的,这次碰到的是java.lang.OutOfMemoryError: GC overhead limit exceeded,下面就来说说这种类型的内存溢出。

简单来说,java.lang.OutOfMemoryError: GC overhead limit exceeded发生的原因是,当前已经没有可用内存,经过多次GC之后仍然没能有效释放内存。

1. 原因

众所周知,JVM的GC过程会因为STW,只不过停顿短到不容易感知。当引起停顿时间的98%都是在进行GC,但是结果只能得到小于2%的堆内存恢复时,就会抛出java.lang.OutOfMemoryError: GC overhead limit exceeded这个错误。Plumbr给出一个示意图:

java.lang.OutOfMemoryError: GC overhead limit exceeded

这个错误其实就是空闲内存与GC之间平衡的一个限制,当经过几次GC之后,只有少于2%的内存被释放,也就是很少的空闲内存,可能会再次被快速填充,这样就会触发再一次的GC。这就是一个恶性循环了,CPU大部分的时间在做GC操作,没有时间做具体的业务操作,可能几毫秒的任务需要几分钟都无法完成,整个应用程序就形同虚设了。

2. 示例

Plumbr上找的一个例子,这里直接给出。

class Wrapper { 
   
  public static void main(String args[]) throws Exception { 
   
    Map map = System.getProperties();
    Random r = new Random();
    while (true) { 
   
      map.put(r.nextInt(), "value");
    }
  }
}

然后设定堆内存是100m,比如java -Xmx100m -XX:+UseParallelGC Wrapper。不同的系统环境可能需要设置不同的堆内存大小,否则会产生不同的OOM错误。其实也算是好理解,因为java.lang.OutOfMemoryError: GC overhead limit exceeded需要有两个条件:98%的时间和2%的内存。如果这两个条件有一个没有达到,结果Map对象扩容,那就可能出现java.lang.OutOfMemoryError: Java heap space这个错误。

3. 解决方法

3.1 JVM参数

JVM给出一个参数避免这个错误:-XX:-UseGCOverheadLimit

但是,这个参数并不是解决了内存不足的问题,只是将错误发生时间延后,并且替换成java.lang.OutOfMemoryError: Java heap space

3.2 堆内存

还有一个偷懒的方法是:增大堆内存。既然堆内存少了,那就增加堆内存即可。

但是,这个方法也不是万能的。因为程序里可能有内存泄露。这个时候即使再增大堆内存,也会有用完的时候。

所以前两个方法都只是治标不治本而已。

3.3 终极方法

其实还是有一个终极方法的,而且是治标治本的方法,就是找到占用内存大的地方,把代码优化了,就不会出现这个问题了。

怎么找到需要优化的代码呢?就是通过heap dump生产jvm快照,通过分析快照找到占用内存大的对象,从而找到代码位置。

通过设置-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heapdump参数来生产快照,然后通过VisualVM或者MAT等工具分析快照内容进行定位。通过这个参数是将发生OOM时的堆内存所有信息写入快照文件,也就是说,如果此时堆内存中有敏感信息的话,那就可能造成信息泄漏了。

推荐阅读


个人主页: http://www.howardliu.cn
个人博文: java.lang.OutOfMemoryError:GC overhead limit exceeded
CSDN主页: http://blog.csdn.net/liuxinghao
CSDN博文: java.lang.OutOfMemoryError:GC overhead limit exceeded

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/158443.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • NTP校时服务器(NTP校时器)资料详解

    NTP校时服务器(NTP校时器)资料详解NTP校时服务器(NTP校时器)资料详解NTP校时服务器(NTP校时器)资料详解NTP网络时间同步摘要:首先对时间同步进行了背景介绍,然后讨论了不同的时间同步网络技术,最后指出了建立全球或区域时间同步网存在的问题。  一、概述  在通信领域,“同步”概念是指频率的同步,即网络各个节点的时钟频率和相位同步,其误差应符合标准的规定。目前,在通信网中,频率和相位同步问题已经基本解决,而时间…

    2022年6月28日
    28
  • 常用的curl命令及参数详解

    前言:经常需要用到curl命令在线上机器中去测试接口,尤其是一些内外网接口、判断线上接口信息等,需要用到curl命令直接测试页面或接口返回值,下面是我常用的curl命令参数及作用:1、curl url作用:获取页面内容或接口响应示例:以爱奇艺视频页领取优惠券为例:curl https://act.vip.iqiyi.com/api/process.action?cb=cb_1540…

    2022年4月8日
    222
  • 只读挂载磁盘linux,linux挂载磁盘就变只读怎么解决

    只读挂载磁盘linux,linux挂载磁盘就变只读怎么解决Linux系统挂载存储变成只读的解决方案:1、mount:用于查看哪个模块输入只读,一般显示为:[root@localhost~]#mount/dev/cciss/c0d0p2on/typeext3(rw)procon/proctypeproc(rw)sysfson/systypesysfs(rw)devptson/dev/ptstypedevpts(r…

    2022年6月19日
    24
  • 电脑快速切换ip软件(好用的换ip软件)

    切换IP软件,切换电脑手机IP如此简单大家在工作和生活中肯定会时不时遇到需要换IP的情况,为了预防需要换IP的时候束手无策,小编在此给大家介绍一款专门用来换IP的软件。打开搜索引擎,不管是百度,狗搜还是360,只要在上面搜索“换IP软件”,立马就会出现非常多的换IP的品牌,有免费的也有付费的,功能都没什么区别,就是换IP。卖IP的这么多,说明换IP的市场还是非常大的!不管你是做什么行业,网络推…

    2022年4月18日
    82
  • Linux中解压zip文件

    Linux中解压zip文件简单记录一下linux中如何解压zip文件首先要安装unzipsudoaptinstallunzip之后可以使用下面命令来解压文件:unzipfile.zip将文件解压到指定文件夹中,如果该文件夹不存在,将会被创建unzipfile.zip-ddirectory…

    2022年5月23日
    50
  • S3C2440体系架构[通俗易懂]

    S3C2440体系架构[通俗易懂]本文是对ARM处理器架构的学习,针对S3C2440型号。参考了Samsung官方的技术文档S3C2440.pdf中的PROGRAMMER’SMODEL一节的内容。ARM和THUMB指令模式S3C2440采用了armv4t指令集,同时支持arm指令集和thumb指令集。arm指令是32位的,而thumb指令是16位的。之所以存在thumb指令是为了降低代码的存储空间。两个指令集之间的切换手动切换

    2022年6月12日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号