CodeWalk

Java Instrumentation与Java Agent机制

作者:我是大山 · 2026-05-30 12:55

详细阐述Java Instrumentation API的工作机制,包括Instrumentation接口的核心方法、ClassFileTransformer的使用、以及premain和agentmain两种Agent加载方式的区别。

回答

我是大山

1. Instrumentation API

  • java.lang.instrument.Instrumentation
  • 核心方法:
    // 添加Transformer
    void addTransformer(ClassFileTransformer transformer, boolean canRetransform);
    // 重新转换已加载的类
    void retransformClasses(Class<?>... classes) throws UnmodifiableClassException;
    // 获取当前JVM中所有已加载的类
    Class[] getAllLoadedClasses();
    // 获取对象大小
    long getObjectSize(Object objectToSize);
    

2. ClassFileTransformer

public interface ClassFileTransformer {
    byte[] transform(
        ClassLoader loader,         // 类加载器
        String className,           // 类名(包路径格式)
        Class<?> classBeingRedefined, // 被重新定义的类
        ProtectionDomain protectionDomain,
        byte[] classfileBuffer     // 原始字节码
    );
}
  • 返回修改后的字节码,返回null表示不修改

3. Agent加载方式

premain(启动时加载)

// MANIFEST.MF: Premain-Class: com.example.MyAgent
public static void premain(String agentArgs, Instrumentation inst) {
    inst.addTransformer(new MyTransformer());
}
  • main()启动前加载
  • 依赖-javaagent:agent.jar启动参数

agentmain(运行时加载)

// MANIFEST.MF: Agent-Class: com.example.MyAgent
public static void agentmain(String agentArgs, Instrumentation inst) {
    inst.addTransformer(new MyTransformer(), true);
    inst.retransformClasses(TargetClass.class);
}
  • 通过Attach API动态附加到目标JVM
  • 可实现热部署

4. 应用场景

  • APM监控(SkyWalking/Pinpoint)
  • 热部署(JRebel/Spring DevTools)
  • 调试诊断(Arthas/Btrace)