开发避坑指南(19) :由GC overhead limit exceeded引发的OOM异常处置方案

异常信息

Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded	
at java.util.HashMap.newNode(Unknown Source)	at java.util.HashMap.putVal(Unknown Source)	at java.util.HashMap.put(Unknown Source)

异常背景

一个老项目使用hibernate,通过hql语句查询大量数据报错。

异常分析

这个错误表明JVM垃圾回收器花费了过多时间却无法释放足够内存,通常由内存泄漏、堆内存不足或代码缺陷引起。hibernate的hql语句是面向对象的方式查询数据,且把很多关联的对象相关的数据也查询出来了,导致大量数据被加载到内存,出现上述内存被耗尽的异常。

解决办法

方案1

增大jvm的初始堆内存(-Xms)和最大堆内存(-Xmx)。Tomcat启动时JVM的初始内存分配由-Xms参数指定,默认值是物理内存的1/64。JVM可以使用的最大内存由-Xmx参数指定,默认值是物理内存的1/4。修改tocmat目录下的/bin/catalina.bat文件,在开头处增加如下配置:

set JAVA_OPTS=%JAVA_OPTS% -XX:PermSize=128M -XX:MaxPermSize=256M -Xms1024M -Xmx2048M

初始堆内存(-Xms)和最大堆内存(-Xmx)可根据实际情况进行调整,可多次增大观察系统的运行情况来确定一个合理的值。

方案2

方案1只是一个临时的紧急解决异常的方案,修改后重启服务即可,但是没有从根源上解决问题。另一个方案就是改写hibernate的hql语句,用原生的sql语句进行查询统计,避免不必要的关联数据查询,尽可能的把只需要的数据加载到内存。

### 解决IntelliJ IDEA中Java程序遇到的`GC overhead limit exceeded`内存溢出问题 当在IntelliJ IDEA中运行Java应用程序时,如果遇到了`java.lang.OutOfMemoryError: GC overhead limit exceeded`错误,则表明垃圾回收器花费了过多时间尝试释放少量堆空间。默认设置下,一旦垃圾收集占用了超过98%的时间而且回收不到2%的堆空间,JVM便会触发此异常[^2]。 为了缓解这一状况并提高性能,可以考虑调整分配给项目的JVM参数来增加可用内存量: #### 修改IDEA中的JVM选项 对于通过IDEA启动的应用,在编辑配置窗口里找到对应的Run/Debug Configurations项下的VM options字段,输入更大的初始和最大堆尺寸值,例如: ```bash -Xms512m -Xmx2048m -XX:MaxPermSize=512m ``` 上述命令设置了最小堆大小为512MB (`-Xms`) 和最大堆大小为2GB (`-Xmx`) ,同时也指定了永久代的最大容量(`-XX:MaxPermSize`) 。这些数值应根据具体需求适当调整[^3]。 #### 配置Gradle构建工具 如果是基于Gradle管理依赖关系及构建过程的话,可以在项目根目录创建或修改`.gradle/gradle.properties` 文件加入如下属性以优化其行为: ```properties org.gradle.daemon=true org.gradle.configureondemand=true org.gradle.jvmargs=-Xmx1024m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 ``` 这里不仅增加了Gradle守护进程使用的最大堆大小至1GB (`-Xmx1024m`) 及永久区大小到同样水平 (`-XX:MaxPermSize=1024m`) ,还启用了发生OOM时自动转储heap dump的功能以便后续诊断(-XX:+HeapDumpOnOutOfMemoryError)[^5]. 另外需要注意的是,确保项目所在的磁盘有足够的剩余空间可供操作;因为即使设定了较高的内存限额,但如果存储设备已满则仍然无法正常工作。 通过以上措施通常能够有效减少甚至消除`GC overhead limit exceeded` 错误的发生频率,从而保障应用稳定性和响应速度。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帧栈

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值