线上现象(各种监控数据)
1.公司项目在监控平台上开始报警(jvm堆内存占用报警,FullGC次数超频率报警)






线上配置(jvm配置,运行时内存分布)
- 项目版本:jdk8 ,spring 5, 默认垃圾处理器 Parallel GC with 43 thread(s) -Xms800m -Xmx800m -XX:MaxPermSize=256m
2.运行时jstat
3.运行时jmap histo
4.heap
5.dump文件1G左右,不发了,稍后看一下MAT分析的图表吧
逻辑分析(定位问题大致方向)
1.通过监控和运行时数据分析,堆内存(年轻代和老年代)、非堆(方法区)、均打满配置内存 2.即使FullGC,堆内存和非堆也只能回收少许内存,并且整体水位倾斜向上,直到内存溢出
通过逻辑分析,内存溢出问题来自于存在泄漏,接下来分析dump文件
内存分析(定位问题确切泄漏源)
采用MAT工具载入dump文件进行leak分析


代码分析(定位导致泄露代码片段)


最终的现象就是老年代、年轻代、非堆内存同时爆满,而又GC不掉,内存泄露直到溢出
代码处理
找到了具体的代码问题,我们将同一个类转换的register在系统启动时注入一次就行,不用每次调用注册,这样的话就不会频繁创建和加载,就可以解决上述问题
本地验证
本地验证错误使用代码,可以复现问题



预发验证




后记
此次问题还是属于比较常见的内存溢出分析,整体按着常用流程没有太多的难点,只有在分析register的时候一时定位不到是开源包的register方法调用的原因(虽然事后感觉很简单,当时也是耗费了30分钟左右才发现)。
troube shooting 三要素: 锻炼自己的逻辑思维、锻炼自己的技术能力、多看多查