Java 有没有办法对加载的类调用advice();ByteBuddy代理之前的方法是什么?
我实现了一个简单的代理,如下所示。它适用于我的自定义Java 有没有办法对加载的类调用advice();ByteBuddy代理之前的方法是什么?,java,byte-buddy,Java,Byte Buddy,我实现了一个简单的代理,如下所示。它适用于我的自定义Foo.class,但我无法为java.net.URL类分配advice 示例测试代码 public class AgentTest { @Test public void advice() throws IOException { Foo foo = new Foo(); File temp = Files.createTempDirectory("tmp").to
Foo.class
,但我无法为java.net.URL
类分配advice
示例测试代码
public class AgentTest {
@Test
public void advice() throws IOException {
Foo foo = new Foo();
File temp = Files.createTempDirectory("tmp").toFile();
Map<TypeDescription, byte[]> map = new HashMap<>();
map.put(new TypeDescription.ForLoadedType(URL.class), ClassFileLocator.ForClassLoader.read(URL.class));
ClassInjector.UsingInstrumentation.of(temp, ClassInjector.UsingInstrumentation.Target.BOOTSTRAP, ByteBuddyAgent.install()).inject(map);
new AgentBuilder.Default()
.disableClassFormatChanges()
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
.with(AgentBuilder.TypeStrategy.Default.REBASE)
.type(is(URL.class).or(is(Foo.class)))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(
isMethod().and(isPublic()).and(named("openConnection")).or(named("myMethod")),
FooAdvice.class.getName()
)
)
.installOnByteBuddyAgent();
foo.myMethod();
}
public static class FooAdvice {
@Advice.OnMethodEnter
public static void enter() {
System.out.println("1- method entered !");
}
@Advice.OnMethodExit
public static void exit() {
System.out.println("2- method exited");
}
}
}
公共类代理测试{
@试验
public void advice()引发IOException{
Foo-Foo=新的Foo();
File temp=Files.createTempDirectory(“tmp”).toFile();
Map Map=newhashmap();
put(新的TypeDescription.ForLoadedType(URL.class)、ClassFileLocator.ForClassLoader.read(URL.class));
ClassInjector.UsingInstrumentation.of(临时,ClassInjector.UsingInstrumentation.Target.BOOTSTRAP,ByteBuddyAgent.install()).inject(映射);
新建AgentBuilder.Default()
.disableClassFormatChanges()
.与(AgentBuilder.重新定义策略.重新转换)
.with(AgentBuilder.TypeStrategy.Default.REBASE)
.type(is(URL.class.)或(is(Foo.class)))
.变换(
新代理builder.Transformer.ForAdvice()
.忠告(
isMethod()和(isPublic())和(命名为(“openConnection”))或(命名为(“myMethod”)),
FooAdvice.class.getName()
)
)
.installOnByteBuddyAgent();
foo.myMethod();
}
公共静态类建议{
@忠告,忠告
公共静态void enter(){
System.out.println(“1-输入的方法!”);
}
@方法索引的建议
公共静态无效退出(){
System.out.println(“2-方法退出”);
}
}
}
是否有任何特定的方法绑定
advice
的java.net.URL类方法,以便在ByteBuddy
代理之前加载该类?默认情况下,Byte Buddy忽略引导和扩展/平台加载程序。您需要将自定义忽略匹配器设置为instrument URL
请注意,如果插入Byte Buddy自身需要的类,尤其是在另一个类的插入过程中Byte Buddy自己加载这些类时,这可能会导致问题。Rafael是正确的,与往常一样。不过,我想更详细地阐述一下您的问题:您在这里遇到了自举问题:
- 建议必须位于引导类路径上,否则不能与引导类
一起使用URL
- 由于注释的原因,建议需要ByteBuddy。所以BB也必须在引导类路径上
- 如果您将示例代码放入一个类中,并且从那里使用BB代理库,那么该类也需要位于引导类路径上。例如,如果您想运行此代码
导入net.bytebuddy.agent.ByteBuddyAgent;
导入net.bytebuddy.agent.builder.AgentBuilder;
导入net.bytebuddy.asm.Advice;
导入java.io.IOException;
导入java.lang.reflect.Method;
导入java.net.URL;
导入静态net.bytebuddy.matcher.ElementMatchers.*;
类代理测试{
公共静态void main(字符串[]args)引发IOException{
ByteBuddyAgent.install();
新建AgentBuilder.Default()
.disableClassFormatChanges()
.ignore(无())
.与(AgentBuilder.重新定义策略.重新转换)
.with(AgentBuilder.RedefinitionStrategy.Listener.StreamWriting.toSystemError())
.with(AgentBuilder.Listener.StreamWriting.toSystemError().with TransformationsOnly())
.with(AgentBuilder.InstallationListener.StreamWriting.toSystemError())
.type(is(URL.class.)或(is(Foo.class)))
.变换(
新代理builder.Transformer.ForAdvice()
.忠告(
isMethod()和(isPublic())和(命名为(“openConnection”))或(命名为(“myMethod”)),
FooAdvice.class.getName()
)
)
.installOnByteBuddyAgent();
新的Foo().myMethod();
}
公共静态类Foo{
public void myMethod()引发IOException{
新网址(“https://google.de”).openConnection();
}
}
公共静态类建议{
@忠告,忠告
公共静态无效输入(@Advice.Origin Method){
系统输出打印项次(“输入”+方法);
}
@方法索引的建议
公共静态无效退出(@Advice.Origin Method){
System.out.println(“退出”+方法);
}
}
}
您需要在Java命令行中添加如下内容:
java-Xbootclasspath/a:/path/to/my class/path/to/byte-buddy-1.10.13.jar/路径/to/byte-buddy-agent-1.10.13.jar。。。代理测试
然后您将得到以下输出:
[Byte Buddy]安装net.bytebuddy.agent.builder.AgentBuilder$Default之前$ExecutingTransformer@27bc2616在太阳仪上。InstrumentationImpl@3941a79c
[Byte Buddy]重新定义批次#0[2个,共2个类型]
[Byte Buddy]转换代理测试$Foo[null,null,loaded=true]
[Byte Buddy]转换java.net.URL[null,null,loaded=true]
[Byte Buddy]重新定义包含2种类型的完整1个批次[0个失败批次]
[Byte Buddy]安装net.bytebuddy.agent.builder.AgentBuilder$Default$ExecutingTransformer@27bc2616在太阳仪上。InstrumentationImpl@3941a79c
输入public void agentSet$Foo.myMethod()会引发java.io.IOException
输入public java.net.URLConnection java.net.URL.openConnection()会引发java.io.IOException
输入public java.net.URLConnection java.net.URL.openConnection()会引发java.io.IOException
退出公共java.net.URLConnection java.net.URL.openConnection()会引发java.io.IOException
输入public java.net.URLConnection java.net.URL.openConnection()会引发java.io.IOException
输入public java.net.URLConnection java.net.URL.openConnection()会引发java.io.IOException
退出公共java.net.URLConnection java.net.URL.openConnection()会引发java.io.IOException
正在退出公共java.net.URLConnection java.net.URL.openConnection()thr