jstat的小伙伴---找出system.gc的调用的小工具

简介: 场景分析现场环境中,造成gc频繁的可能性之一就是通过system.gc主动调用了gc。这种情况出现在开发人员业务代码,或者是jdk自身的代码中(例如nio)。

场景分析

现场环境中,造成gc频繁的可能性之一就是通过system.gc主动调用了gc。这种情况出现在开发人员业务代码,或者是jdk自身的代码中(例如nio)。我们可以通过jstat -gccause查看gc的原因,如果真的是system.gc,那么找出调用的代码就是继续解决问题的关键。

查看system.gc的调用

如果说查看代码调用,那么jstack就是首选,仔细想想,代码的触发时机不定,怎么才能去在合适的时候打印堆栈呢,最简单的想法就是定时的去调用,这个方法是有用的,只不过在频繁调用的时候,是可以捕获到的。可是万一不频繁调用呢。

当我们想知道自己的代码在什么时候被调用,那么最好的方式就是在自己的方法里去打印堆栈。这样就知道是谁调用的了,也不用担心是调用的时机等等。

解决方案也就出来了,那就是在system.gc调用的时候顺便打印一下堆栈。system是jdk的类,可以自己编写一个system类替换掉jdk的,只不过不想用的时候还得改回来。为了灵活我们选择动态修改字节码。

字节码改造

我们先想想打印堆栈的代码

        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        for (StackTraceElement element : stackTrace) {
            System.out.println(element);
        }

现在呢,我们就在system.gc前调用这个方法。这里修改字节码的方式,我们使用asm。

            InsnList list = new InsnList();
            list.add(getLabelNode());
            list.add(new MethodInsnNode(INVOKESTATIC, "com/xp/agent/core/ThreadInfo", "getStack", "()V", false));
            insns.insert(list);

修改完就大功告成。

细节补充

字节码是改成了,但是我们的那个类路径得让加载system类的classloader(bootstrapclassloader)找到我们的类。否则会抛出classnotfind或者noclassdefineerror。这里我们通过增加配置文件的方式。

Agent-Class: com.xp.agent.main.Main
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Class-Path: trace-0.0.1-SNAPSHOT-common.jar asm-all-6.0_BETA.jar
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_121
Boot-Class-Path: trace-0.0.1-SNAPSHOT-agentcore.jar

代码地址

大佬如果喜欢,可以点个星鼓励一下。

https://github.com/xpbob/lightTrace

目录
相关文章
|
5月前
|
Java UED
Java面试题:描述JVM中垃圾收集的Stop-The-World现象及其影响
Java面试题:描述JVM中垃圾收集的Stop-The-World现象及其影响
70 1
|
6月前
|
Java
JVM打印GC信息
JVM打印GC信息
【面试题精讲】JVM中哪些对象可以被称为GC ROOT对象
【面试题精讲】JVM中哪些对象可以被称为GC ROOT对象
|
Java
JVM学习笔记-如何在IDEA打印JVM的GC日志信息
若要在Idea上打印JVM相应GC日志,其实只需在Run/Debug Configurations上进行设置即可。
129 0
调用 System.gc() 后究竟发生了什么?
调用 System.gc() 后究竟发生了什么?
|
算法 Java API
Java虚拟机System.gc()解析
对于Java语言来说是不用刻意手动去释放内存,同时,也尽可能不需要手动去干预Java虚拟机的GC行为。在本篇文章中,我们试图从多个方面去解析有关System.gc()API调用的最常见问题。希望对需要了解这块技术的朋友有所帮助。
209 0
|
缓存 安全 Java
没有发生GC也进入了安全点?这段关于安全点的JVM源码有点意思!
没有发生GC也进入了安全点?这段关于安全点的JVM源码有点意思!
249 1
|
存储 监控 算法
System.gc()与Runtime.gc()的区别
System.gc()与Runtime.gc()的区别
206 0
|
消息中间件 Java 测试技术
JVM相关 - 深入理解 System.gc()
本文基于 Java 17-ea,但是相关设计在 Java 11 之后是大致一样的 我们经常在面试中询问 System.gc() 究竟会不会 立刻 触发 Full GC ,网上也有很多人给出了答案,但是这些答案都有些过时了。本文基于最新的信息 Java 的下一个即将发布的 LTS 版本 Java 17(ea)的源代码,深入解析 System.gc() 背后的故事。
|
运维 监控 Kubernetes
JVM 输出 GC 日志导致 JVM 卡住
JVM 输出 GC 日志导致 JVM 卡住
JVM 输出 GC 日志导致 JVM 卡住