• 一次OutOfMemoryError: GC overhead limit exceeded


    现象:

    由于需要将mysql表中的过期数据在凌晨定时读取出过滤后转入到MongoDB,一个转换SQL达到百行,而且有几十个,集中运行后程序反馈异常:

    Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded

    Heap内存:1.5G,程序在Docker容器限制使用内存2G。

    监控到内存GC变化:

    Heap内存占用骤升至1.2G,然后不停的进行FullGC,而且间隔非常短,从下图中可以看出PermGen稳定,这也表明读取的数据由于太大是直接进入了老年代内存。

    这时候CPU也彪升接近100%

    请求访问时长也加长,异常反馈。

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

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

    网友的解决建议:

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

    // 不推荐
    -XX:-UseGCOverheadLimit

    我告诉你,这是一种完全错误的做法。因为 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 错误的时间。

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

    • 哪类对象占用了最多内存?
    • 这些对象是在哪部分代码中分配的?
    作者:欢醉
    公众号【一个码农的日常】 技术群:319931204 1号群: 437802986 2号群: 340250479
    出处:http://zhangs1986.cnblogs.com/
    码云:https://gitee.com/huanzui
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    Top
  • 相关阅读:
    如何在Mac下配置多个Java版本
    robotframework-SikuliLibrary 第三方库
    点击按钮,按钮没有悬浮效果,不能拖拽元素。
    robot framework ——关键字run keyword if 如何在一个条件下接多个执行语句
    iOS测试中发现一个textview控制,使用clear()无法清除文字
    AppiumLibrary 关键字文档
    "startIWDP": true
    Proxifier ,CCProxy 新发现的东西。
    第一次Git上传本地项目到github上 的命令
    c#之数组
  • 原文地址:https://www.cnblogs.com/zhangs1986/p/11362019.html
Copyright © 2020-2023  润新知