If I have the following Class
named Dog
public class Dog {
private String name = "Spike";
private int age = 3;
public Dog() {}
public String getName() {
return name;
}
}
How would I declare ByteBuddy for use in a javaagent
to redefine the Dog
class to provide the method getAge
which returns an int
?
The desired (effective) class should look like this below and be able to be invoked by doing dog.getAge()
public class Dog {
private String name = "Spike";
private int age = 3;
public Dog() {}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
Attempt 1: I've tried changing the syntax to what I understand to be correct (PitBullInterceptor.class found below)
new AgentBuilder.Default()
.redefine(Dog.class)
.defineMethod("getAge", int.class, Method.PUBLIC)
.intercept(MethodDelegation.to(PitBullInterceptor.class))
.installOn(instrumentation);
I have the following issue in my attempts
The method redefine(Class) is undefined for the type AgentBuilder.Default
Which is basically a syntax error. I'm not sure which DynamicTypes
or MethodDelegations
/ElementMaters
to use to configure the Agentbuilder
to perform to this type of redefine/rebase as Rafael Winterhalter describes it
Attempt 2: I've tried using it with ByteBuddyAgent.install
public static void main(String[] args) throws Exception {
ByteBuddyAgent.install();
new ByteBuddy()
.redefine(Dog.class)
.defineMethod("getAge", int.class, Method.PUBLIC)
.intercept(MethodDelegation.to(PitBullInterceptor.class))
.make()
.load(Dog.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent())
.getLoaded()
.newInstance();
}
public static class PitBullInterceptor {
private static int age = 1;
public static int getAge() {
return age;
}
}
Produces the error:
java.lang.UnsupportedOperationException: class redefinition failed: attempted to add a method
Attempt 3: Lastly, I've tried doing so with the agent built
public static void premain(String arguments, Instrumentation instrumentation) {
new AgentBuilder.Default()
.disableClassFormatChanges().with(RetransformationStrategy.RETRANSFORM)
.with(new ByteBuddy()
.redefine(PitBull.class)
.method(ElementMatchers.named("getAge"))
.intercept(MethodDelegation.to(PitBullInterceptor.class))
.make()
.load(Dog.class.getClassLoader()))
.installOn(instrumentation);
}
public static class PitBull {
private String name = "Kujo";
public String getName() {
return name;
}
}
public static class PitBullInterceptor {
private static int age = 3;
public static int getAge() {
return age;
}
}
Produces:
java -javaagent:agent.jar -jar app.jar
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:491)
at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:503)
Caused by: java.lang.IllegalStateException: Class already loaded: class io.xxx.agent.boss.Agent$PitBull
at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.load(ByteArrayClassLoader.java:363)
at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default$WrappingDispatcher.load(ClassLoadingStrategy.java:367)
at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default.load(ClassLoadingStrategy.java:148)
at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:101)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6317)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6305)
at io.xxx.agent.boss.Agent.premain(Agent.java:21)
... 6 more
*** java.lang.instrument ASSERTION FAILED ***: "result" with message agent load/premain call failed at t:\workspace\open\src\java.instrument\share\native\libinstrument\JPLISAgent.c line: 422
FATAL ERROR in native method: processing of -javaagent failed, processJavaStart failed