当前位置:   article > 正文

巨大结果集引起疯狂FullGC怎么排查

巨大结果集引起疯狂FullGC怎么排查

巨大结果集引起疯狂FullGC怎么排查

笔者经常遇到这样一个问题。就是SQL写的不好,从数据库里面捞出来一个非常巨大的结果集,导致Java疯狂的进行Full GC,然后失去响应。找出来导致巨大结果集的sql有一个套路可以轻松找到。今天我就分享这个技巧

先dump再重启

遇到FullGC导致系统失去响应,那第一步当然是用jmap进行java的heap dump然后重启恢复。jmap命令如下:

jmap -dump:format=b,file=rheap.hprof [你的进程pid] 

当然了,在JVM参数里面最好加上

-XX:+HeapDumpOnOutOfMemoryError

参数,这样在java进程在出现OOM的时候可以打印出dump文件,不至于找不到痕迹。

用MAT(MemoryAnalyzer进行分析)

由于素材并不在这台电脑上,所以就无法截图展示了。利用MAT打开dump文件之后,它会自动分析哪个占用的内存最大,并给出内存泄露信息。例如这样:

基本的排查方法就是看这个MAT提示有内存溢出的类是怎么产生的。毫无疑问,我们的巨大结果集肯定是SQL产生的。如何找到这个SQL呢?看下图: 我们可以做一下推理,如果还在FullGC,明显这个ResultSet还在内存里,那么对应的JDBC连接里肯定还在绑定这条sql,并不会被释放。同时这个系统最前端接收的调用请求肯定还在,因为这个请求还没有结束。如下图所示:

当我们从ResultSet按图索骥找到对应的JDBC Connection后,可以看到其中运行的SQL,这样我们就知道到底是哪个SQL了。

想知道SQL还不够?想知道哪个请求参数导致的?

很简单,由于我们的数据库交互基本都是在一个线程里面的。那么从ResultSet在MAT里面找到其中的CurrentThread,然后再在这个CurrentThread中找到你对应的Request请求类,就可以看到传输的参数了!由于JVM可达性的原理,这些对象肯定不会被回收。

还想更简单,更快吗?

就用MAT非常NB的OQL功能吧,看到某个结果集基本就能够想到哪几种请求会导致这个Request。直接用OQL Select那些请求Class,看一看就行了。因为请求一般很快,存留在heap dump中的很少。

使用OQL,例如BinaryOutpuArchive是你的请求参数,通过OQL搜索,会找到这个heapdump中的所有对象。并能够展示出对象中的所有信息。那么,如果一个请求参数不合理,就很容易看出来了!

总结

内存泄露问题大部分时候用MAT就可以解决问题,今天笔者介绍了一个小套路。怎么通过MAT方便的找到对应的SQL和对应的请求参数,希望能够对读者有所帮助。

END

推荐好文

强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!

为什么MySQL不推荐使用uuid或者雪花id作为主键?

为什么建议大家使用 Linux 开发?爽(外加七个感叹号)

IntelliJ IDEA 15款 神级超级牛逼插件推荐(自用,真的超级牛逼)

炫酷,SpringBoot+Echarts实现用户访问地图可视化(附源码)

记一次由Redis分布式锁造成的重大事故,避免以后踩坑!

十分钟学会使用 Elasticsearch 优雅搭建自己的搜索系统(附源码)


本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/422361
推荐阅读
相关标签
  

闽ICP备14008679号