异常信息
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语句进行查询统计,避免不必要的关联数据查询,尽可能的把只需要的数据加载到内存。
1238

被折叠的 条评论
为什么被折叠?



