javaagent 探针运行时重定义class
一 、手动编写agent类
1.premain
随JVM启动时调用,必须通过
-javaagent:jarpath[=options]
指定agent.jar
since 1.5
public static void premain(String agentArgs, Instrumentation inst) {
}
public static void premain(String agentArgs) {
}
2.agentmain
JVM启动后,通过进程ID,attach关联
since 1.6
public static void agentmain (String agentArgs, Instrumentation inst) {
}
public static void agentmain (String agentArgs) {
}
参考:
示例代码
Java类动态加载(二)——动态加载class文件
IDEA + maven 零基础构建 java agent 项目
二、通过bytebuddy简化agent操作(推荐)
采用的是agentmain方式,运行时attach关联。
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
</dependency>
获取instrumentation 对象,调用重定义class接口
final Instrumentation instrumentation = ByteBuddyAgent.install();
/**
* The redefinition may change method bodies, the constant pool and attributes.
* The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance. These restrictions maybe be lifted in future versions.
* @param clazz
* @param classByte
* @throws UnmodifiableClassException
* @throws ClassNotFoundException
*/
public void redefine(Class clazz, byte[] classByte) throws UnmodifiableClassException, ClassNotFoundException {
ClassDefinition def1 = new ClassDefinition(clazz, classByte);
instrumentation.redefineClasses(new ClassDefinition[]{def1});
}
注意:运行修改方法体、常量池;但禁止新增、移除、重命名方法和属性字段。(将来可能会取消该限制)。
java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
参考:
arthas attach源码