javaagent加载
静态加载
通过VM启动参数-javaagent
将agent的jar包挂载到目标JVM程序,和目标程序一起启动。
启动参数
"-javaagent:
[=
premain方法
- premain()方法会在程序main方法执行之前被调用,此时大部分Java类都没有被加载("大部分"是因为,agent类本身和它依赖的类还是无法避免的会先加载的),是一个对类加载埋点做手脚(addTransformer)的好机会。
- 如果此时premain方法执行失败或抛出异常,那么JVM的启动会被终止。
- premain() 中一般会编写如下步骤:
注册类的 ClassFileTransformer,在类加载的时候会自动更新对应的类的字节码
写法示例:
// Java agent指定的premain方法,会在main方法之前被调用
public static void premain(String args, Instrumentation inst) {
// Instrumentation提供的addTransformer方法,在类加载时会回调ClassFileTransformer接口
inst.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) {
// TODO 字节码修改
byte[] transformed = null;
return transformed;
}
});
}
加载流程
agent中的class由系统ClassLoader(默认AppClassLoader)加载,premain() 方法会调用 Instrumentation API,然后 Instrumentation API 调用 JVMTI(JVMTI的内容将在后面补充),在需要加载的类需要被加载时,会回调 JVMTI,然后回调 Instrumentation API,触发ClassFileTransformer.transform(),最终修改 class 的字节码。
premain() 方法会调用 Instrumentation API,然后 Instrumentation API 调用 JVMTI(JVMTI的内容将在后面补充),在需要加载的类需要被加载时,会回调 JVMTI,然后回调 Instrumentation API,触发ClassFileTransformer.transform(),最终修改 class 的字节码。
图片来源:【JVM】Java agent超详细知识梳理
动态加载
动态加载,即 JVM 启动后的任意时间点(即运行时),通过Attach API动态地加载 Java agent,对应的是 agentmain() 方法。
agentmain()方法
对于VM启动后加载的Java agent,其agentmain()方法会在加载之时立即执行。如果agentmain执行失败或抛出异常,JVM会忽略掉错误,不会影响到正在 running 的 Java 程序。
一般 agentmain() 中会编写如下步骤:
- 注册类的 ClassFileTransformer
- 调用 retransformClasses 方法对指定的类进行重加载
字节码操作工具库
asm
低级别的字节码操作框架,提供对类文件的细粒度控制,适合需要高性能的场景。
特点:直接操作JVM指令,学习曲线较高,但灵活性极强。
典型应用:CGLIB动态代理、代码覆盖率工具(如JaCoCo)
byte buddy
轻量级的字节码生成/操作库,支持动态创建类或修改现有类的字节码,常用于实现Java Agent的字节码增强功能。
特点:API简洁,性能优于ASM和Javassist,支持Java 11+的模块化系统。
典型应用:APM工具(如SkyWalking)、动态代理框架等
javassist
基于源码级别的字节码操作库,允许开发者通过字符串拼接生成或修改类。
特点:易用性高,适合快速开发,但性能略低于ASM和Byte Buddy。
典型应用:动态生成类、AOP实现
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?