-
-
Save raphw/34c0e2fffe2ee7b4f02f to your computer and use it in GitHub Desktop.
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(); | |
} | |
} | |
} |
Ah, I figure it out, I can get the Context value now, : )
public static class SystemClassLoaderClassInterceptor {
public static String intercept(@SuperCall Callable<String> zuper) throws Exception {
Class<?> contextClazz = Class.forName("me.i36.bytebuddy.Main$Context", true, null);
Method method = contextClazz.getMethod("get");
method.setAccessible(true);
System.out.println(Thread.currentThread().getName() +
" - Intercepted! context value : " + method.invoke(contextClazz)); // the value X
return zuper.call();
}
}
You probably have the class included in your agent jar and also attach it to the boot loader. This way it will be loaded in the system loader before it is attached to boot and therefore be loaded twice. With different class loaders, the two classes are different. Try not including it as a ".class" file in the boot loader.
You probably have the class included in your agent jar and also attach it to the boot loader. This way it will be loaded in the system loader before it is attached to boot and therefore be loaded twice. With different class loaders, the two classes are different. Try not including it as a ".class" file in the boot loader.
how can I try not to including it as a ".class" file in the boot loader ?
Have a look at ClassInjector
and Instrumentation
which both offer APIs for that.
Have a look at
ClassInjector
andInstrumentation
which both offer APIs for that.
OK, thanks raphw.
But I have already injected the
Context
class into the boot loader.Why can't I get the
Context
class loaded by the boot loader in the SystemClassLoaderClassInterceptor class ?(on line 110, the class loader of
Context
class is not the boot loader)