又是一次由于线上报警机制开启的排查问题之旅。某日,钉钉机器人疯狂报警:java
接着就是申请机器权限去排查问题,既然是频繁Full GC,那咱们排查问题的思路就应该是找到引发Full GC的缘由。引发频繁Full GC的常见缘由有这么几点:git
gc日志永远都是咱们排查gc问题最好的工具,因此强烈建议你们在线上配置-XX:+PrintGCDetails -Xloggc:/data/logs/gc.log方便咱们去定位问题。因为当前项目没有配置,只好用jstat -gccause去监测,博主监测了五分钟左右,获得以下信息:新生代、老年代、元空间内存还不少,FGC涨了9次,而且对应的LGCC都显示为System.gc.因为虚拟机参数并无去配置-XX:MaxDirectMemorySize,因此其堆外内存受限于当前物理机内存,故咱们能够经过top去查看进程占了多少内存和经过free -m查看空闲内存(固然visualvm的插件和perftools都是查看堆外内存使用状况很好的工具,不了解自行谷歌)。通过内存分析和业务分析以后,初步判定不是堆外内存致使的,而是由项目中有调用System.gc().github
首先对项目全局进行搜索System.gc(),若是没有查到,那么就极可能是依赖的jar包里存在调用,如何在jar包中查找呢?在这里给你们推荐一款插件Btracegithub地址。BTrace是Java的安全可靠的动态跟踪工具。 他的工做原理是经过 instrument + asm 来对正在运行的java程序中的class类进行动态加强。说他是安全可靠的,是由于它对正在运行的程序是只读的。也就是说,他能够插入跟踪语句来检测和分析运行中的程序,不容许对其进行修改。所以他存在一些限制:数组
根据官方声明,不恰当的使用Btrace会致使jvm崩溃,因此在上生产环境以前,必定要在本地充分验证脚本的正确性。Btrace的常见使用场景有:安全
Btrace依赖于JDK,首先要安装好JDK并配置JDK的环境变量。jvm
1.下载安装包工具
下载地址:https://github.com/btraceio/btrace/releases/tag/v1.3.11
2.解压缩
修改目录权限:源码分析
3.配置环境变量
而后source更新环境变量
4.编写btrace脚本性能
import static com.sun.btrace.BTraceUtils.jstack; import static com.sun.btrace.BTraceUtils.println; import static com.sun.btrace.BTraceUtils.str; import static com.sun.btrace.BTraceUtils.strcat; import static com.sun.btrace.BTraceUtils.timeMillis; import com.sun.btrace.annotations.BTrace; import com.sun.btrace.annotations.Kind; import com.sun.btrace.annotations.Location; import com.sun.btrace.annotations.OnMethod; import com.sun.btrace.annotations.TLS; @BTrace public class MyTest { @OnMethod(clazz = "java.lang.System", method = "gc" ) public static void startMethod(){ println("****************************************"); jstack(); println("****************************************"); } @OnMethod(clazz = "java.lang.System", method = "gc", location = @Location(Kind.RETURN)) public static void endMethod(){ println("========================================="); jstack(); println("========================================="); } }
5.运行btrace
经过jps -l得到进程的pid,而后经过 btrace <pid> <btrace_script> >> gc.txt & 之后台任务的方式去开启btrace脚本监听对应进程,将对应的栈信息保存到gc.txt中。
6.关闭btracespa
通过长达一天的监控,终于抓到了对应的调用栈:
缘由是项目中用到了jxl的Workbook来作Excel相关的功能,每次关闭Workbook的时候都会调用System.gc
至此,咱们就已经抓住了致使频繁Full GC的鬼了,改动方法也特别简单,在构造WorkBook的时候,将其成员变量WorkbookSettings的成员变量gcDisabled设置为true便可避免此问题,或者添加vm参数-Djxl.nogc=true(不太推荐).
每次排查问题的时候遇到了不少困难,在总结的时候却又不知道该说些什么~.~。特别感谢提供帮助的笨神、阿飞和零度。