Java Instrumentation与Java Agent机制
详细阐述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)