I am writing a Java agent with ByteBuddy API. Therefore, I want to get in touch with the method delegation of classes that are alredy loaded using the retransformation capabilities of the Bytebuddy DSL. When I start the application with the -javaagent
parameter everything works fine and the console output gets changed but when attaching the java agent at runtime the agentmain method is executed but the console output does not get changed. Maybe im missing some further ByteBuddy configuration. Any help would be appreciate!
Here is the agent code :
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! ");
}
}
Here is the application code :
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);
}
}
}
Here is the code to attach the agent:
public class Attacher {
public static void attach(String jarFile, String pid) {
try {
ByteBuddyAgent.attach(new File(jarFile), pid);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
You probably need to add .disableClassFormatChanges()
as most JVMs do not support changing the shape of classes upon a retransformation.
Also, consider registering an AgentBuilder.Listener
to see why a class cannot be transformed. The instrumentation API suppresses all errors otherwise.
Normally, when retransforming, the Advice
API is better suited for transformation. It supports most features of the delegation API but works slightly different.