项目上线,发现集群机器每隔1小时会准时进行fullgc,JMC中显示了System.gc()触发了fullgc:

代码搜了一下自然是搜不到显示调用这个代码的(谁会这么干!拍死!!!)依赖jar包中到是有,但是看看也不像。

在大神的建议下,决定使用Btrace跟踪一下调用栈。

Pom依赖:

<dependency>
    <groupId>com.sun.tools.btrace</groupId>
    <artifactId>btrace-boot</artifactId>
    <version>1.2.3</version>
</dependency>

 

java类:

import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.OnMethod;

import static com.sun.btrace.BTraceUtils.jstack;
import static com.sun.btrace.BTraceUtils.println;

@BTrace
public class GCBtrace {

    @OnMethod(clazz = "java.lang.System", method = "gc")
    public static void onSystemGC() {
        println("entered System.gc()");
        jstack();
    }

}

 Btrace包:https://github.com/btraceio/btrace

本地测试类:

public class GCTest {

    static int a = 1;
    public static void main(String[] args){

        for (int a =0;a<10000;a++){
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 触发gc
            a();
        }
    }

    public static void a(){
        b();
    }
    public static void b(){
        c();
    }
    public static void c(){
        System.out.println("第"+a+++"次触发gc");
        System.gc();
    }
    
}

 

跟踪过程:

Step1. GCTest本地跑起来

Step2. Btrace放到固定目录下

Step3. GCBtrace.java 测试类 放到固定目录下

Step4. jps获取当前进程id

       

Step5. 进入btrace/bin文件夹下后,命令跟踪【./btrace 80543 /Users/***/GCBtrace.java】:

:bin ***$ ./btrace 80543 /Users/***/GCBtrace.java 
  entered System.gc()
  java.lang.System.gc(System.java)
  btrace.GCTest.c(GCTest.java:40)
  btrace.GCTest.b(GCTest.java:36)
  btrace.GCTest.a(GCTest.java:33)
  btrace.GCTest.main(GCTest.java:28)

 

 如上可以详细看到GC调用堆栈。

 将Btarce和GCBtrace.java 拷贝到线上,即可查出到底是哪调用的System.gc().

 

特别注意:若植入btrace监控代码后,监控逻辑会一直在,直到重启应用。

 

参考:

1、 https://www.jianshu.com/p/dbb3a8b5c92f

2、https://blog.csdn.net/byzh4/article/details/79550490

3、http://huanghaifeng1990.iteye.com/blog/2121419

posted on 2018-11-23 16:05  大辉_FFf  阅读(206)  评论(0编辑  收藏  举报