CodeWalk

Java Agent premain与agentmain详解及Arthas原理

作者:小字辈 · 2026-05-30 12:55

深入分析Java Agent的premain(启动时加载)和agentmain(运行时Attach)两种模式,以及诊断工具Arthas利用Agent实现热替换、方法追踪的核心原理。

回答

小字辈

1. premain模式

// 启动时执行,在main方法之前
public static void premain(String agentArgs, Instrumentation inst) {
    // 添加ClassFileTransformer,在类加载时修改字节码
    inst.addTransformer(new MyTransformer());
}
  • 打包要求:MANIFEST.MF必须包含Premain-Class
  • 启动命令java -javaagent:agent.jar -jar app.jar
  • 限制:只能拦截加载前的类,已加载的类无法修改

2. agentmain模式

// 运行时动态附加到JVM
public static void agentmain(String agentArgs, Instrumentation inst) {
    inst.addTransformer(new MyTransformer(), true);
    // 对已加载的类重新转换
    inst.retransformClasses(TargetClass.class);
}
  • 打包要求:MANIFEST.MF必须包含Agent-ClassCan-Retransform-Classes: true
  • Attach APIcom.sun.tools.attach.VirtualMachine):
    VirtualMachine vm = VirtualMachine.attach(pid); // 附加到目标进程
    vm.loadAgent(agentJarPath, args);              // 加载Agent
    vm.detach();                                    // 分离
    

3. Arthas原理深度解析

  • Attach到目标JVM:使用VirtualMachine.attach(pid)
  • 核心组件
    • Instrumentation:retransformClasses动态替换字节码
    • ASM/Byte Buddy:修改字节码插入监控逻辑
    • SPI加载:自定义ClassLoader加载Arthas的Class
  • watch/trace命令:通过Instrumentation + ASM在方法前后插入切面
  • ognl表达式:利用ognl提取上下文变量
  • 热替换(redefine)retransformClasses实现方法替换

4. 注意事项

  • MANIFEST.MF需设置Can-Retransform-Classes: true
  • agentmain需要tools.jar(JDK 8)或jdk.attach模块(JDK 9+)