OSSClient引起的内存泄漏

本文介绍了一种内存泄漏问题的排查及解决过程,包括如何通过工具分析堆转储文件找到问题根源,以及如何修复由OSS客户端造成的内存泄漏。

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

最近公司的服务总是时好时坏,CPU和内存经常会占用到100%,导致服务不可用,重启之后就好了,但是过一段时间又会出现同样的情况,因此怀疑是出现了内存泄漏。没办法,只能一步步分析看问题出在哪里。

第一步

找到进程的端口号 ps -ef | grep XXX,其中XXX代表该进程的关键字。
使用 jmap -histo:live port | head -10 初步找出占用内存最大的对象,但是由于本次泄漏找到的对象比较奇怪,因此需要更加细的来找到泄漏的对象。

第二步

使用 jmap -dump:live,format=b,file=heap.hprof port 将该进程的堆转储到文件,file的值表示转储后的名字,live是可选项,如果输入则表示只输出活的对象到文件。

第三步

将堆转储文件下载到本地电脑,利用工具进行分析。在这里我推荐 Eclipse 的 MAT 分析工具。分析完成后如下图所示:
1093758-20180508111923642-940709765.png
这里重点关注 Leak Suspects, 打开后如下图所示:
1093758-20180508112113965-1402842601.png
MAT指出了可能存在内存泄漏的情况,点击 Details查看详情:
1093758-20180508112019368-1640561458.png
可以很清楚的看到存在大量的 org.apache.http.impl.conn.PoolingHttpClientConnectionManager 对象,存放在同一个ArrayList当中,并且被 com.aliyun.oss.common.comm.IdleConnectionReaper 实例持有。

第四步

分析 IdleConnectionReaper 源码:
1093758-20180508112202105-602083390.png
该类继承自 Thread,且在类加载过程中就会初始化一个 ArrayList 实例。和分析报告吻合,但是当我想要查看究竟是哪里使用了这个类时却无法准确定位到。于是我想到从创建OSSClient对象开始查找。
从最初的创建OssClient对象开始查找,最后定位到
1093758-20180508112331418-1816446301.png
该方法,项目中使用的创建方式为 DefaultServiceClient,进入该构造方法:
1093758-20180508112407245-899522657.png
由于默认配置是使用 IdleConnectionReaper 来管理过期连接,因此进入到这个方法中:
1093758-20180508112434346-861492208.png
1093758-20180508112441687-1943870354.png
可以看到,OSS客户端专门建立了一个线程来管理其所需要的HTTP连接。而在业务中每次都会创建一个新的OSS客户端对象,那么每次也都会往该List中添加新的连接。由于这些连接对象一直被持有,所占用的内存无法释放,越到后面所创建的对象越多,占用的内存越大,一直到内存被使用完为止。
同时我可以联想到,应该有一个方法来手动释放掉已使用的连接,回到OSSClient,有一个 shutdown 方法:
1093758-20180508112504870-1215725529.png
1093758-20180508112515729-1244000878.png
将本次创建的Http连接对象从管理队列中移除,并且关闭。

总结

找到问题可能的原因以后,我在本地模拟线上不停创建OSSClient的场景,然后分析堆转储文件,MAT 给出的结论是一致的,同时在调用创建对象后再调用 shutdown 方法,内存不再不停的增长。

转载于:https://www.cnblogs.com/cbzj/p/9007260.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值