Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 有没有办法对加载的类调用advice();ByteBuddy代理之前的方法是什么?_Java_Byte Buddy - Fatal编程技术网

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