最近线上碰到了一个应用频繁full gc,但是看内存使用率却很低,感觉不是内存空间不够导致的gc,查看gc日志发现是由于显式调用了System.gc()
导致的gc,全局搜索应用却发现应用代码中并没有调用System.gc()
,因此怀疑是依赖的三方包中有显式调用System.gc
的行为,那么怎么查看是谁调用了呢?
代码里找不出来,便想着看线上调用的时候能不能把调用堆栈记录下来,恰好发现了Arthas,能完美解决这个问题,使用Arthas不需要重启应用。见issue
:
第一步,由于java.lang.System
是JDK自带的类,Arthas默认关闭了对JDK类的自带类的增强,需要通过options
命令打开
第二步,使用stack
命令,观察谁调用了java.lang.System#gc
本地测试代码如下:
public class PurchaseTest {
public static void main(String[] args) throws Exception{
System.out.println("main start");
while(true) {
sleep();
}
}
public static void testSystemGC(){
System.out.println("gc start");
System.gc();
}
public static void sleep(){
try {
System.out.println("sleep start");
TimeUnit.SECONDS.sleep(10);
}catch (Exception e){
}
testSystemGC();
}
}
监控结果如下:
![9fa649180ef92f13e382659b347811b7.png](https://img-blog.csdnimg.cn/img_convert/9fa649180ef92f13e382659b347811b7.png)
只要发生了System.gc()
调用,便会被监控到,可以参考issue
里把监控信息重定向到文件,这样便不用一直盯着等待System.gc
被调用。