线上服务内存泄漏异常排查

5 篇文章 0 订阅
3 篇文章 0 订阅
本文详述了一次线上服务出现的Java.lang.UnsupportedOperationException异常,通过排查发现是由于单例对象中的成员变量Map无限扩容导致的内存泄漏。分析了问题现象、定位内存泄漏对象,并提出了解决方案,包括避免单例模式、及时清理Map对象和使用局部变量。强调在使用Java中IOC注入时,需要注意对可无限扩容数据结构的管理,以防止内存泄漏。
摘要由CSDN通过智能技术生成

线上异常:

Java.lang.UnsupportedOperationException:null

在这里插入图片描述

排查步骤:
1.获取服务的对应的进程PID 22188
在这里插入图片描述

2.jstat命令查看jvm的GC情况 (以Linux为例)

jstat -gcutil 22188 5000

在这里插入图片描述

NGCMX:新生代最大容量
NGC:当前新生代容量
S0C:第一个幸存区大小
S1C:第二个幸存区的大小
EC:伊甸园区的大小
OGCMN:老年代最小容量
OGCMX:老年代最大容量
OGC:当前老年代大小
OC:当前老年代大小
MCMN:最小元数据容量
MCMX:最大元数据容量
MC:当前元数据空间大小
CCSMN:最小压缩类空间大小
CCSMX:最大压缩类空间大小
CCSC:当前压缩类空间大小
YGC:年轻代gc次数
FGC:老年代GC次数

现象:
所有的对象基本上都在老年代中,导致JVM 一直在 GC

3.查看 线上服务堆栈中创建的对象信息:

jmap -histo 22188 | more 

在这里插入图片描述
4.定位到具体的内存泄漏对象

一般系统自带的对象不做过多关注,自定义的对象过多需要多关注
比如上述的

   4:       4000000       64000000  com.example.trashrecysling.TestBeanTrash

这个对象有4百万个,占用的内存大小为64000000bytes~61MB

这个对象明显有问题,直接去代码中找到对应的实体在哪些地方被创建了。

5.找大对象被创建的地方
在这里插入图片描述
在这里插入图片描述
6.定位内存泄漏的原因
1.首先通过接口调用,Controller中通过@Autowired 注入一个对象 FinalClassVariables
在这里插入图片描述
2.FinalClassVariables这个对象是通过默认注入的方式注入到Controller中,所以这个对象是个单例对象
在这里插入图片描述
3.单例对象中的一个成员变量 finalVari Map 这个对象在 setFinalVari方法被调用的时候数据塞入,但是没有数据移除的代码

6.总结
通过Java 中IOC 机制默认注入的对象都是单例的对象,在单例对象中声明成员变量时,如果变量是个能够无限自增扩容的数据结构时,需要注意及时释放这个对象,否则就会导致对象被无限扩容,最终导致内存泄漏;
解决方法:①将Bean生成方式改成非单例模式;②在Map对象使用完毕之后将对象中的值清除掉;③将Map对象降级成局部变量;
个人推荐使用第三种方式,写代码的人不同,很有可能漏掉①②步

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值