JavaAgent介绍 | 基本介绍及无侵入打印方法耗时

闲聊

最近在配置skywalking的过程中发现了-javaagent:这个配置,这里做一个简单的学习

什么是JavaAgent

网上似乎没有直接的文档介绍这个,只找了instrument包的相关文档,其内容页。其中的内容也都是介绍javaagent相关。

instrument包下核心就是字节码增强,此包下有2个核心接口ClassFileTransformerInstrumentation

  • ClassFileTransformer:An agent provides an implementation of this interface in order to transform class files.

  • ClassFileTransformer:代理需要实现这个接口,并对class文件转化(增强)

  • Instrumentation:This class provides services needed to instrument Java programming language code.

  • Instrumentation:Instrumentation 为代码增强提供了必要的服务和功能。

有什么用及怎么用

有什么用

代码增强可以用于监控代理、分析器、覆盖分析器和事件记录器。

怎么用

上面介绍了这么多编码过程,如果想要能使用,则需要打成jar包,具体使用需要通过-javaagent来让代码运行。总算知道为啥没有文档了,-javaagent主要是用来让代理生效的,核心是instrument包

如果伴随jar包启动,需要创建premain方法,并在MANIFEST.MF中指定Premain-Class: com.mountain.monk.MyAgent

如果是在启动后,再进行代理,则需要创建agentmain方法,并在MANIFEST.MF中指定Agent-Class: com.mountain.monk.MyAgent

实现一个计算函数执行时间的功能

  1. 随便创建一个类,创建premain方法,此处我使用了javassist来生成字节码
java 复制代码
public class MyAgent {

    public static void premain(String agentArgs, Instrumentation inst) {
        inst.addTransformer(new TimeTransformer(),true);

    }



    public static class TimeTransformer implements ClassFileTransformer {


        @Override
        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
            // 这里我们限制下,只针对目标包下进行耗时统计
            if (!className.startsWith("com/mountain/monk/")) {
                return classfileBuffer;
            }

            CtClass cl = null;
            try {
                ClassPool classPool = ClassPool.getDefault();

                cl = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));


                for (CtMethod method : cl.getDeclaredMethods()) {
                    method.addLocalVariable("start", CtClass.longType);
                    method.insertBefore("start = System.currentTimeMillis(); ");
                    method.insertAfter("System.out.println(\"「monk」methodName:" + method.getName() + ", cost: \" + (System" +
                            ".currentTimeMillis() - start));");
                }

                return cl.toBytecode();
            } catch (Exception e) {
                System.err.println("Error transforming class: " + className);

                e.printStackTrace();
            }
            return classfileBuffer;

        }
    }
}
  1. 创建MANIFEST.MF,注意最后要空一行
java 复制代码
Premain-Class: com.mountain.monk.MyAgent
Can-Redefine-Calsses: true
Can-Retransform-Classes: true
  1. 配置maven,注意:我这里需要把依赖打包进去
maven 复制代码
<build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

    </build>
  1. 配置Idea启动参数

-javaagent:/Users/chenhui/learn/monk_note/self_agent/target/self_agent-1.0-SNAPSHOT-jar-with-dependencies.jar

  1. 随便找一个代码启动
相关推荐
玛卡巴卡0117 小时前
Maven 从入门到实战:搞定依赖管理与 Spring Boot 项目构建
java·spring boot·maven
vortex517 小时前
用 Scoop 快速部署 JeecgBoot 开发环境:从依赖安装到服务管理
java·windows·springboot·web·开发·jeecg-boot
جيون داد ناالام ميづ17 小时前
Spring Boot 核心原理(一):基础认知篇
java·spring boot·后端
fantasy5_518 小时前
手撕vector:从零实现一个C++动态数组
java·开发语言·c++
十八旬18 小时前
RuoYi-Vue3项目定制修改全攻略
java·windows
任风雨18 小时前
3.1.1.Java基础知识
java·开发语言
脸大是真的好~19 小时前
黑马JAVA+AI 加强03-集合-Collection-List和Set集合-迭代器(Iterator)遍历-并发修改异常
java
cj63411815019 小时前
DBeaver连接本地MySQL、创建数据库表的基础操作
java·后端
书院门前细致的苹果19 小时前
深入理解 Java 多线程与线程池 —— 从原理到实战
java·开发语言
大G的笔记本20 小时前
用 Redis 的 List 存储库存队列,并通过 LPOP 原子性出队来保证并发安全案例
java·数据库·redis·缓存