在运维线上系统的时候,发现一个比较奇怪的现象,每隔一个小时出现一次full gc的情况,而且full gc偶尔也会出现,问题十分奇怪,jvm 堆内存虽然说是比较小,但是实际的交易量很小,也会出现这种情况。
处理方法:
1.在应用的启动参数中,增加-XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC
-XX:HeapDumpPath=/tmp/,对发生full gc之前和之后,对jvm内存进行一次dump,jvm会将文件生成到/tmp/ 这个目录, 之后分析,没有发现什么大的对象。
2.观察gc的日志信息发现,full gc是由system.gc()触发的
![9413e4d67e56521128b3b0dba89e5686.png](https://i-blog.csdnimg.cn/blog_migrate/e3c6cf83a787ac81f13ae02041ae2d81.jpeg)
那么问题来了,谁调用了这个system.gc(),在代码中找寻了半天都没有
这里介绍两种方式解决,第一种btrace工具,通过编写btrace代码,对system.gc 方法进行监控,获取执行的堆栈信息.
![f3edc0e5ed1e07347f2b1ad63de38b6e.png](https://i-blog.csdnimg.cn/blog_migrate/52e65c7a504dc3e5c9a79df5e3b0ac73.jpeg)
在应用程序上执行,btrace javaPid javaFile.java (需要提前下载btrace工具),javaPid就是对应的java进程号,javaFile.java就是编写的java脚本。执行之后,我们发现:
![ea848622d38cac4f9a5fdb80c16636d2.png](https://i-blog.csdnimg.cn/blog_migrate/217765df9454c6a924e4de393ca78f7b.jpeg)
是由于一个导出的excel工具触发的system.gc(),也就是每次导出excel就会有触发full gc这种情况.
第二个方法,就是使用阿尔萨斯这个工具进行排查,这个工具更加快捷
快速入门 - Arthas 3.1.0 文档 有兴趣可以看看这个工具,
执行执行wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
之后选定需要监控的java 进程id,之后执行options unsafe true,这就可以监控系统类,然后执行stack java.lang.System gc,就是监控gc这个方法,执行,就会打印方法上下文的堆栈
![4ff3f25bb858626dda4c4a7c5f8af692.png](https://i-blog.csdnimg.cn/blog_migrate/44f6d3bd0720e3ef0fa99d5e655d2262.jpeg)
大家可以根据,自己的情况,选择合适的工具,排查问题.解决由system.gc()引发的full gc可以在jvm参数中添加,-XX:-+DisableExplicitGC,或者实际项目情况中使用的组件设置,避免system gc触发full gc