最近线上碰到了一个应用频繁full gc,但是看内存使用率却很低,感觉不是内存空间不够导致的gc,查看gc日志发现是由于显式调用了
System.gc()
导致的gc,全局搜索应用却发现应用代码中并没有调用
System.gc()
,因此怀疑是依赖的三方包中有显式调用
System.gc
的行为,那么怎么查看是谁调用了呢?
代码里找不出来,便想着看线上调用的时候能不能把调用堆栈记录下来,恰好发现了Arthas,能完美解决这个问题,使用Arthas
不需要重启应用
。见
issue
:
https://github.com/alibaba/arthas/issues/20github.com
第一步,由于
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();
}
}
监控结果如下:
只要发生了
System.gc()
调用,便会被监控到,可以参考
issue
里把监控信息重定向到文件,这样便不用一直盯着等待
System.gc
被调用。