Error when trying to modify the response of a method assigned to a public static final config variable
Closed this issue · 9 comments
jdk corretto-17.0.7 , and bytebuddy version is 1.14.9
I get :
None of [public static java.lang.Object com.bcp.fraud.streams.Main$MyInterceptor.intercept(com.bcp.fraud.streams.Main$MyCallable,java.lang.Object[]) throws java.lang.Exception] allows for delegation from public static org.apache.kafka.common.config.ConfigDef io.confluent.kafka.schemaregistry.rest.SchemaRegistryConfig.baseSchemaRegistryConfigDef()
this is my code:
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(AgentBuilder.TypeStrategy.Default.REDEFINE)
.with(new FlowListener())
.ignore(nameStartsWith("net.bytebuddy."))
.type(ElementMatchers.named("io.confluent.kafka.schemaregistry.rest.SchemaRegistryConfig"))
.transform((builder, typeDescription, classLoader, module, protectionDomain) -> {
//return builder;
return builder
.method(named("baseSchemaRegistryConfigDef"))
.intercept(MethodDelegation.to(MyInterceptor.class));
})
.installOn(inst);
What I want is to modify a routine of that method in Java, what should I use?
I use net.bytebuddy.agent.ByteBuddyAgent.install method to instrumentation at runtime.
What's your interceptor class, including annotations and imports?
Hi , thanks for replying,
Is it technically possible to modify this method?
--> Code:
`import io.confluent.kafka.schemaregistry.rest.SchemaRegistryConfig;
import io.confluent.rest.RestConfigException;
import javassist.NotFoundException;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.MemberSubstitution;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.JavaModule;
import org.apache.kafka.common.config.ConfigDef;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.Properties;
import static net.bytebuddy.matcher.ElementMatchers.*;
public class MainX2 {
public static void main(String[] args) throws RestConfigException, NotFoundException {
SchemaRegistryConfig test = new SchemaRegistryConfig(new Properties());
Instrumentation instrumentation = ByteBuddyAgent.install();
new AgentBuilder.Default()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
.with(AgentBuilder.RedefinitionStrategy.Listener.StreamWriting.toSystemError())
.with(AgentBuilder.Listener.StreamWriting.toSystemError().withTransformationsOnly())
.with(AgentBuilder.InstallationListener.StreamWriting.toSystemError())
.type(ElementMatchers.named("io.confluent.kafka.schemaregistry.rest.SchemaRegistryConfig"))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) {
try {
return builder
.visit(MemberSubstitution.strict()
.method(named("baseSchemaRegistryConfigDef"))
.replaceWith(MainX2.class.getMethod("baseSchemaRegistryConfigDef"))
.on(any()));
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
}).installOn(instrumentation);
SchemaRegistryConfig teSchemaRegistryConfig = new SchemaRegistryConfig(new Properties());
System.out.println(teSchemaRegistryConfig.baseSchemaRegistryConfigDef().configKeys().size());
}
public static ConfigDef baseSchemaRegistryConfigDef() {
return new ConfigDef();
}
`
I would like to know if it is possible to replace the body of that method with a modified one. I have tried some examples but no success.
It is, but the static initializer will not be rerun on a retransformation. In this case, you would need to hook before the class is loaded for the first time.
I agree Rafael, with AgentBuilder could I achieve it?
If you have any reference it would help me a lot for what I am looking for
You mean rerun the static initializer? That is not possible, unfortunately, the JVM does not support it.
If I understood what you indicated... ("you would need to hook before the class is loaded for the first time.")
could you give me some reference on how I could resolve this case? thank you so much :)
You are doing it right, but there's nothing that can fix your problem if the initializer already ran.
Thank you very much for the support! , I found everything about bytebuddy interesting.