inputstreamreader未关闭会导致oom_如何排查和解决java项目内存溢出(OOM)问题

前言

现象:生产环境java项目,运行一周后出现OOM问题,初步排查是内存泄漏问题导致OOM。

在讨论内存泄漏问题之前,我们首先看一下对内存泄漏的定义,在维基百科上,对内存泄漏问题的定义如下:

内存泄漏(Memory leak)是在计算机科学中,由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。

内存泄漏通常情况下只能由获得程序源代码的程序员才能分析出来。(见:https://zh.wikipedia.org/wiki/%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F)

内存泄漏这个名词在工作中经常听到,当出现了这些问题的时候应该怎么去解决呢?下面我将介绍最近一次工作中遇到的内存泄漏的解决过程,方便大家参考。

下面从现象开始说起:

现象

机器为阿里云ECS实例,4核16g,分配参数-server -Xms8192m -Xmx8192m,运行期间执行jstat -gcutil [pid] 1000 3000统计如下,FGC次数和持续时间表现正常,:

809dce520c004980244a6769905f103d.png

运行大约7天后会发现,情况变为这样:

8fb265bbfd56f5bf6520857c24166fca.png
296f6e998668b54b751f1888f9afa6ca.png

FGC次数和时间显著提升,但是发现内存丝毫没有减少的趋势,这个时候怀疑就是内存泄漏的问题了,一定是哪里使用了某个资源没有被释放,

解决思路

这个时候如果项目比较一般都能猜出是哪里使用了的对象没有释放,但是如果项目较大,很难直接定位代码中哪里因为疏忽没有释放内存,这个时候需要借用jmap命令导出内存dump文件,使用MAT(Memory analy tools)工具对内存情况进行分析,分析结果如下:

ff1d909007550d660a12e5665feec570.png
c7d0876f94696a3b8879ce1b02ed10c2.png
2dd616210f64131d0b993570b3c860d2.png
52f92c205f1f638f841c1fcd3c721a36.png

相信看到这,大家应该知道哪个类占用了大量内存吧?没错就是,org.apache.http.impl.conn.PoolingHttpClientConnectManager,那么接下来要确定是代码哪里使用了这个类,可能是代码直接使用,也可能是引用的组件中使用的。

继续跟踪发现:

5d79e78015234c416dea7b384db4b872.png

代码中在使用OSS SDK进行文件的上传和下载,查看代码发现:

78558686afd2f8b3584df9612d106c00.png

此处创建了OSSClient但是未对连接进行释放,由阿里云文档描述得知(https://www.alibabacloud.com/help/zh/doc-detail/32010.htm),在使用了OSSClient之后,需要调用shutdown()方法进行资源释放,因为此处的业务场景是用户上传图片、资源,比较频繁,用户每上传一次就会新增一个OSSClient对象,由于没有释放,出现内存泄漏,导致过一段时间内存就会逐渐增大,达到最大内存后,出现OOM。

最后,此次内存泄漏问题最终由增加shutdown()代码后,测试通过发布后解决而告一段落,在解决过程中发现几个信息特别重要:

  1. 对JVM的理解和内存泄漏相关知识的理解,推荐看如下书籍对相关知识系统学习,书名:《深入理解Java虚拟机》、《Java性能调优指南》、《Java性能优化权威指南》
  2. 熟悉调试命令,不过一般公司研发可能没有权限去执行这些命令,但是学会后出问题后能够配合运维一起排查问题,否则出问题后根本无从下手,推荐如下文档:https://www.cnblogs.com/baihuitestsoftware/articles/6382733.html
  3. https://docs.oracle.com/javase/7/docs/technotes/tools/share/jstat.html
  4. 学会分析工具的使用如MAT(https://blog.csdn.net/Jin_Kwok/article/details/80326088)和一台内存够大的电脑(此次出问题后,导出来的文件10个G,要不是家里有台25G台式机还不好排查问题,8G的mac伤不起)。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值