一次内存溢出事故

您所在的位置:网站首页 jprofiler工具引起gc时间变长 一次内存溢出事故

一次内存溢出事故

#一次内存溢出事故| 来源: 网络整理| 查看: 265

事情经过

事情是这样,公司项目是一个springcloud的微服务,服务每隔半个月就会发生一次频繁的fullGC。后来定位到是缓存不合理导致的,该缓存的key是一条条sql,value是表名。这个缓存是用来干嘛呢?查了下他主要是分库组件sharding-jdbc在执行sql时,首先要通过这个缓存来获取sql对应的表。这个缓存设计的大小是1000,超时时间1天,而且用的一个LocalCache是强引用。因为在我们的生产环境中经常会有一下批量插入查询的操作,一个插入一千条数据的sql放在这个地方,就可能是一个 2.5MB左右的字符串。也就说极端情况,如果有几百条这种大sql被缓存进来,那么一下子就会占用1G的内存,而我们的应用堆大小只有5个GB,所以悲剧时不时就发生了。后来发了个邮件给架构组同事,修改了这部分代码,把sql变成sql的hashCode,问题就解决了。

jprofiler 使用过程

分析出来后原因是挺简单的,这里记录一下用到的工具jprofiler,如何用jprofiler分析GCRoot。首先用jmap获取java进程的dump文件,命令如下:

jmap -dump:live,format=b,file=dump.hprof 5092

然后,用jprofiler导入dump文件,按照下图顺序点击,在弹出的窗口选择上面用jmap生成的文件即可。 在这里插入图片描述 导入后的界面长这样: 在这里插入图片描述 接下来,点击某一类型的对象,选择 incoming reference 进入: 在这里插入图片描述 进入后即可看到一个个的对象如下图所示,点击上方的size,将对象按大小排序后即可重点分析大对象。点击对应的对象,再点击 show paths to GC 即可看到一级一级的引用关系。以我选中的这个对象为例,看样子是一些jar包路径,查看gcroot,显示是由System类中的静态变量 props 持有。 在这里插入图片描述

总结

在整个分析溢出异常的过程中,基本的思路是有的:

1.保存异常现场(jmap获取dump文件),生产环境中如果由多个微服务部署,可以直接dump,否则的话还是要先重启,保证生产,再想办法再测试环境复现问题。 2.jprofiler分析大对象的持有者。 3.结合代码进行优化。

在分析过程中,我更多的时间反而是花在了工具学习上,期间尝试过Jvisualvm(java自带的),发现不太好用。后来换成了jprofiler。 最后发现原因后,成就感是满满的,感觉自己不光是在CRUD了~~



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3