最近线上碰到了一个应用频繁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
     
     被调用。
    
 
