JDBC4Connection中的hashmap不释放,导致OutOfMemory内存泄漏

本文分析了一次因JDBC4Connection中HashMap未正确释放导致的OutOfMemory内存泄漏问题。在多线程环境下,每批次10个线程处理1W数据时,处理5W数据后出现内存泄漏。通过memoryanalyzer分析,发现JDBC4Connection在同一事务中缓存所有操作的SQL脚本,未释放导致内存溢出。最终解决方案为修改SQL查询方式并确保线程结束后释放资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JDBC4Connection中的hashmap不释放,导致OutOfMemory内存泄漏

背景:

每天跑批的一个分润任务出现了OutOfMemory内存泄漏,和小伙伴一起查找问题,一直也没有定位问题。

任务描述:

多线程操作一批数据,每批次10个线程,每个线程处理1W数据。处理大概5W左右会出现OutOfMemory内存泄漏。

定位问题:

一开以为有大量对象没有释放,所以手动进行释放处理。测试重跑任务,只是有一点点效果,问题依旧还在。

怀疑数据库配置问题,检查了mysql所有主从机器,没有发现配置异常。

最后找到运维大神导出当时dump日志。

获取dump日志:

ps:这里说一下运维大神的硬盘速度是真的快,几秒就传过来了。给了我一个log结尾的文件,我一开始还以为给错了。

解压文件,改文件后缀为.hprof文件格式。打开memory analyzer,open head dump。

memory analyzer分析:

剖析问题:

看到有一堆JDBC4Connection,不知道什么东东。还特意看了一下我们之前关注的对象的内存占用。

从上面的图也能看出来每个子线程占用的内存情况。

结合代码剖析问题:

JDBC4Connection里面有很多hashmap,应该是任务查询的数据。找到的执行查询的sql。对应到代码查看问题。

解决方案:

目前只是把先查询再删除改为直接删除。(此解决方案不可行)

最后的想法:

因为这个查询操作是在子线程里操作的。查询走的mysql从库,还有一个mysql主库在此日志同样有连接,但是没有这样的问题。目前怀疑的问题是:

  1. 子线程操作JDBC4Connection查询不释放
  2. 因为分表实现才用的是当当的sharding,怀疑是sharding的影响
  3. 怀疑mysql驱动bug问题影响

未完待续。。。

 

2021年03月30日20:16:32

这个问题好久之前就改好了,今天看到了帖子,结束一个帖子吧。

之前的解决方案不可以,直接删除使用shardingjdbc会导致数据库MySQL表死锁。

最终定位的问题是JDBC4Connection在同一主事物中缓存了所有操作的执行SQL脚本。应该属于之前猜测的第一种情况。

JDBC4Connection中有一个对象储存了SQL脚本。每个SQL脚本大约占用2KB。所有连接没有释放,缓存SQL脚本的对象越来越大,导致了oom。

SQL里写法是 字段 as 别名类型,500左右各字段,整个SQL脚本占用 2Kb左右字节。后期改为 select * ,之前基本查询了所有字段。每个子线程处理完,释放对象操作。最后从根本解决问题。

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值