当前位置:   article > 正文

java排查full gc_巨大结果集引起疯狂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文件之后,它会自动分析哪个占用的内存最大,并给出内存泄露信息。例如这样:

68bfdf3476ef0c6acd06a67b23f67ce1.gif

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

68bfdf3476ef0c6acd06a67b23f67ce1.gif

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

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

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

还想更简单,更快吗?

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

68bfdf3476ef0c6acd06a67b23f67ce1.gif

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

总结

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

END

推荐好文

68bfdf3476ef0c6acd06a67b23f67ce1.gif

原文始发于微信公众号(Java笔记虾):巨大结果集引起疯狂FullGC怎么排查

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/422366
推荐阅读
相关标签
  

闽ICP备14008679号