记一次服务Full GC背后的内存泄漏问题,真是匪夷所思( 二 )
文章插图
6. 项目中哪里使用了ClassPathList?分析到这里 , 似乎离真相越来越近了 。 到底这个ClassPathList在项目中哪里使用到了?通过前面的分析知道了ClassPathList的整体引用关系链:AppClassLoader -> ClassPool类的defaultPool字段 -> ClassPoolTail类的source字段 -> ClassPathList类的pathList
6.1 ClassPathList源码
文章插图
可以看到 , ClassPathList有两个属性 , 一个是next , 结合之前MAT的分析 , ClassPathList的确就是一个链表的结构 。 随着时间的增长 , ClassPathList不断新增 , 链表也随之变得越来越大 , 最后内存占用逐渐上升 。 另一个path字段属于ClassPath类型 , ClassPath是个接口 , 查看它的实现类 , 发现一个似曾相识的名称ClassClassPath , 之前分析对象统计信息时 , 还有一个类的对象数量是和ClassPathList一样的 , 正是这个ClassClassPath 。 每新增一个ClassPathList , 都会伴随着新增对应的ClassPath对象 , 这也解释了为什么两者数量是一致的了 。
6.2 ClassClassPath源码
文章插图
通过注释知道 , 这个ClassClassPath的作用大概就是 , 利用一个叫ClassPool的对象 , 可以调用其insertClassPath方法来新增一个ClassClassPath对象 , insertClassPath方法内部通过头插法将ClassClassPath添加到ClassPathList链表 , 从而形成一个search-path , 然后通过这个search-path能够获取到某一个Class类的信息 。
文章插图
于是尝试着搜了一下 , 看看项目中有没有调用到insertClassPath方法的地方 。 意外发现一个类 ,
文章插图
这不就是我们项目用来打印方法入参、执行耗时、上报metrics的@AutoLog的实现类吗 。
文章插图
可以看到getParams方法中调用了insertClassPath , 注解@AutoLog的printParams默认为true , 也就是每次调用都需要打印方法入参 , 每次打印前都要调用getParams先获取参数名称 。 因此每次都会insertClassPath , 从而导致ClassPathList链表越来越大 。
至此 , 内存泄漏的元凶已经找到 。 解决方法也就简单了 。 因为目标只是想得到方法的参数名称 , 通过JoinPoint其实能直接获取到 , 因此可以改成JoinPoint获取的方式 。
7. 压测为了进行对比 , 分别在修改前后各进行一次压测 。 压测JVM参数大致与线上一致 , 为了尽快看到效果 , 只是调小了heap的大小 。 -Xms200m -Xmx200m
7.1 修改前
文章插图
ClassPathList数量不断增长
文章插图
年老代每次能回收的垃圾越来越少 , 每次回收过后的剩余空间也越来越小 。 最终整个年老代被撑满
文章插图
虽然还没触发OOM , 但是CPU负载飙高 , 从基本都在处于频繁的FULLGC状态
7.2 修改后
文章插图
ClassPathList已经被消灭掉了
文章插图
FullGC也趋于规律化了 。 每次回收的垃圾大致都相同
文章插图
8. 后记
- 很多时候只依靠简单的对象统计信息 , 不足以定位问题 , 需要使用完整HeapDump , 通过MAT进一步分析 。 如果只需分析年老代对象 , 可以使用OQL过滤 。 可用如下方式可获得老生代地址:
第二种方式是使用vjmap的命令 , 在-old, -sur, -address 中 , 都会打印出该区间的地址
第三种方式 , 使用vjmap的address命令 , 快速打印各代地址 , 不会造成过长时间停顿 。
详情参考:
- 亲选服务使用JDK8 ,默认的GC收集算法;-XX:+UseParallelOldGC 。 使用Parallel Scavenge(年轻代)+Parallel Old(老年代)的组合进行GC 。 这是一套注重吞吐量的收集器 。 吞吐量=程序运行时间/(程序运行时间+GC时间) 。 假设运行时间99秒、GC时间1秒 。 吞吐量=99% 。 但是对于有一定并发量的在线应用来说 , GC时停顿1秒是挺大影响的 。 因此后续可根据情况调整使用CMS
- 人民币|天猫国际新增“服务大类”,知舟集团提醒入驻这些类目的要注意
- 出海|出海日报丨短视频生产服务商小影科技完成近4亿元 C 轮融资;华为成为俄罗斯在线出售智能手机的第一品牌
- 成为佛山移动服务体验官 表白留言赢取百元话费
- 迁徙|网红迁徙记:哪里才是奶与蜜之地?
- 简单|密码太难记不住,太简单不安全,怎么办?
- 截图|笔记本截图快捷键是什么
- 统计|多久才能换一次手机?统计机构数据有点意外
- 电池容量|Windows 自带功能查看笔记本电脑电池使用情况,你的容量还好吗?
- 贵阳|捷顺科技(002609.SZ)中标贵阳智慧停车公共信息服务平台系统建设项目
- 出行|哈啰出行的“纵横术”