Class用Bytebuddy Agent重新改造
Class Retransformation with Bytebuddy Agent
我正在用 ByteBuddy API 编写一个 Java 代理。因此,我想接触已经使用 Bytebuddy DSL 的重新转换功能加载的 类 的方法委托。当我使用 -javaagent
参数启动应用程序时,一切正常并且控制台输出发生了变化,但是在运行时附加 java 代理时,执行了 agentmain 方法,但控制台输出没有发生变化。也许我缺少一些进一步的 ByteBuddy 配置。任何帮助将不胜感激!
这是代理代码:
public class AgentMain {
private static final String CLASS = "testing.Test";
private static final String METHOD = "doSomething";
public static void premain(String agentArgs, Instrumentation instrumentation) {
System.out.println("premain...");
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(ElementMatchers.named(INSTRUMENTED_CLASS))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder transform(
DynamicType.Builder builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule javaModule
)
{
return builder.method(named(INTERCEPTED_METHOD))
.intercept(MethodDelegation.to(Interceptor.class));
}
}).installOn(instrumentation);
}
public static void agentmain(String agentArgs, Instrumentation instrumentation) {
System.out.println("Running agentmain...");
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(ElementMatchers.named(INSTRUMENTED_CLASS))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder transform(
DynamicType.Builder builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule javaModule
)
{
return builder.method(named(INTERCEPTED_METHOD))
.intercept(MethodDelegation.to(Interceptor.class));
}
}).installOn(instrumentation);
}
}
public class Interceptor {
public static void doSomething(String string) throws Exception {
System.out.println("Intercepted! ");
}
}
这是应用程序代码:
public class Main {
public static void main(String args[]) throws Exception {
while (true) {
Thread.sleep(1000);
String say = "Not intercepted!";
Test test = new Test();
test.doSomething(say);
}
}
}
这是附加代理的代码:
public class Attacher {
public static void attach(String jarFile, String pid) {
try {
ByteBuddyAgent.attach(new File(jarFile), pid);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
您可能需要添加 .disableClassFormatChanges()
,因为大多数 JVM 不支持在重新转换时更改 classes 的形状。
另外,考虑注册一个AgentBuilder.Listener
,看看为什么class不能转换。检测 API 会抑制所有其他错误。
一般情况下,再转化时,Advice
API更适合转化。它支持委托的大部分功能 API 但工作方式略有不同。
我正在用 ByteBuddy API 编写一个 Java 代理。因此,我想接触已经使用 Bytebuddy DSL 的重新转换功能加载的 类 的方法委托。当我使用 -javaagent
参数启动应用程序时,一切正常并且控制台输出发生了变化,但是在运行时附加 java 代理时,执行了 agentmain 方法,但控制台输出没有发生变化。也许我缺少一些进一步的 ByteBuddy 配置。任何帮助将不胜感激!
这是代理代码:
public class AgentMain {
private static final String CLASS = "testing.Test";
private static final String METHOD = "doSomething";
public static void premain(String agentArgs, Instrumentation instrumentation) {
System.out.println("premain...");
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(ElementMatchers.named(INSTRUMENTED_CLASS))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder transform(
DynamicType.Builder builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule javaModule
)
{
return builder.method(named(INTERCEPTED_METHOD))
.intercept(MethodDelegation.to(Interceptor.class));
}
}).installOn(instrumentation);
}
public static void agentmain(String agentArgs, Instrumentation instrumentation) {
System.out.println("Running agentmain...");
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.type(ElementMatchers.named(INSTRUMENTED_CLASS))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder transform(
DynamicType.Builder builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule javaModule
)
{
return builder.method(named(INTERCEPTED_METHOD))
.intercept(MethodDelegation.to(Interceptor.class));
}
}).installOn(instrumentation);
}
}
public class Interceptor {
public static void doSomething(String string) throws Exception {
System.out.println("Intercepted! ");
}
}
这是应用程序代码:
public class Main {
public static void main(String args[]) throws Exception {
while (true) {
Thread.sleep(1000);
String say = "Not intercepted!";
Test test = new Test();
test.doSomething(say);
}
}
}
这是附加代理的代码:
public class Attacher {
public static void attach(String jarFile, String pid) {
try {
ByteBuddyAgent.attach(new File(jarFile), pid);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
您可能需要添加 .disableClassFormatChanges()
,因为大多数 JVM 不支持在重新转换时更改 classes 的形状。
另外,考虑注册一个AgentBuilder.Listener
,看看为什么class不能转换。检测 API 会抑制所有其他错误。
一般情况下,再转化时,Advice
API更适合转化。它支持委托的大部分功能 API 但工作方式略有不同。