背景:
早上晨会,运维小哥说63环境特别卡,用户一直在反映了,我说好的,我看一下什么问题。
按照平常的步骤巡检,1.CPU,2.磁盘,3.服务状态,看了一下都没啥问题,然后我就猜:难道是fullGC了?
输入 命令jps找到服务pid,jstat -gc pid 1000 10,果然:
看看fullGC了150+次肯定代码出问题了,查看日志有Java heap space的OOM异常,服务配置的有OOM时导出dump文件,OOM时无非两种原因,1.真的内存不够用了,2.循环产生对象导致内存溢出。
分析dump文件有三种,1.MAT工具,2.jvisualvm工具(java自带),3.jhat工具(java自带),本人更加倾向于MAT工具,来吧,开干!
1.打开MAT工具,装入dump文件解析(如果dump文件过大,该过程会比较久,而且还会导致mat工具内存溢出,修改初始化文件MemoryAnalyzer.ini中的-Xmx的值,重新装入即可)
2.解析成功
3.点击reports下的leak suspects
mat将问题已经分析出来了,一共三个问题,一个一个来看
Problem suspect 1
点击details
看到这个ResultSet是不是有点熟悉,就是jdbc操作数据库的返回值,看到这里,我再猜:难道是数据库返回了一个非常大的集合?
继续猜:jdbc肯定得有sql语句去操作数据库,先找出sql验证一下,是不是结果有很多
点击owningStatement,左边orginalSql中有sql
拿着这个sql去数据库验证
妈耶,数据库返回122464条数据到java,而且返回的字段还这么多,老铁,瞬间是不是知道问题出在哪里了?
想要找到具体哪些代码用到了这个sql,就需要去反推,xml -->dao -->service
搞不懂当时写代码的人是怎么想的,你可以选择分页啊,再不济,你可以只取有用的列,不仅减少内存的占用,还会降低网络通信的消耗,而且还可能用上覆盖索引增加sql的性能,这又让我想起了select * 的弊端!感兴趣的老铁可以去看看,今天又是收获满满的一天!