Skip to content

Instantly share code, notes, and snippets.

@raphw
Last active March 6, 2025 18:06
Show Gist options
  • Save raphw/34c0e2fffe2ee7b4f02f to your computer and use it in GitHub Desktop.
Save raphw/34c0e2fffe2ee7b4f02f to your computer and use it in GitHub Desktop.
An example agent that intercepts a method of the bootstrap class loader.
package net.bytebuddy;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassInjector;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.matcher.ElementMatchers;
import java.io.File;
import java.lang.instrument.Instrumentation;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.util.Collections;
import java.util.concurrent.Callable;
public class BootstrapAgent {
public static void main(String[] args) throws Exception {
premain(null, ByteBuddyAgent.install());
HttpURLConnection urlConnection = (HttpURLConnection) new URL("http://www.google.com").openConnection();
System.out.println(urlConnection.getRequestMethod());
}
public static void premain(String arg, Instrumentation inst) throws Exception {
File temp = Files.createTempDirectory("tmp").toFile();
ClassInjector.UsingInstrumentation.of(temp, ClassInjector.UsingInstrumentation.Target.BOOTSTRAP, inst).inject(Collections.singletonMap(
new TypeDescription.ForLoadedType(MyInterceptor.class),
ClassFileLocator.ForClassLoader.read(MyInterceptor.class).resolve()));
new AgentBuilder.Default()
.ignore(ElementMatchers.nameStartsWith("net.bytebuddy."))
.enableBootstrapInjection(temp, inst)
.type(ElementMatchers.nameEndsWith(".HttpURLConnection"))
.transform(new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader) {
return builder.method(ElementMatchers.named("getRequestMethod")).intercept(MethodDelegation.to(MyInterceptor.class));
}
}).installOn(inst);
}
public static class MyInterceptor {
public static String intercept(@SuperCall Callable<String> zuper) throws Exception {
System.out.println("Intercepted!");
return zuper.call();
}
}
}
@JoseCanova
Copy link

JoseCanova commented Mar 6, 2025

Found the problem
The Class.forName works fine.
but both methods bellow don`t

Object clazz = org.nanotek.config.spring.BootstrapAgent.class.getClassLoader()
.getResourceAsStream("org/nanotek/config/spring/repositories/SimpleTableRepository.class");
System.err.println("clazz "+clazz);

Object resource = org.nanotek.config.spring.BootstrapAgent.class.getClassLoader()
.getResource("org/nanotek/config/spring/repositories/SimpleTableRepository.class");
System.err.println("resource "+resource);

Now, I understood that a "ClassLoader" need to be used to override the methods that SpringData uses to scan the packages,
and also "register" the instances of DynamicTypes manually but, using the sequence of registration used by the framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment