4

我在获取一个使用 Byte Buddy 的简单示例时遇到问题,这是我的代码:

import static java.util.Arrays.asList;
import java.util.stream.Stream;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodDelegation;

public class Foo {
  public static class Bar {
    public void bar (String s, Integer i) {
      System.out.println ("s:" + s + " i:" + i);
    }
  }
  public static class Baz {
    public void baz (Integer i, String s) {
      System.out.println ("i:" + i + " s:" + s);
    }
  }

  public static void main (String[] args) {
    try {
      Class<?> c = new ByteBuddy ()
        .subclass (Object.class)
        .defineMethod ("bar", Void.class, asList (String.class, Integer.class), 1)
        .intercept (MethodDelegation.to (new Bar ()))
        .defineMethod ("baz", Void.class, asList (Integer.class, String.class), 1)
        .intercept (MethodDelegation.to (new Baz ()))
        .make ()
        .load (Foo.class.getClassLoader (), ClassLoadingStrategy.Default.WRAPPER)
        .getLoaded ();
      Stream.of (c.getDeclaredMethods ()).forEach (System.out::println);
    } catch (Exception e) {
      e.printStackTrace ();
    }
  }
}

我希望工作并将调用转发到受人尊敬的拦截器实例,但是我得到了这个异常:

java.lang.IllegalArgumentException: None of [protected void java.lang.Object.finalize() throws java.lang.Throwable, public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException, public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException, public final void java.lang.Object.wait() throws java.lang.InterruptedException, public boolean java.lang.Object.equals(java.lang.Object), public java.lang.String java.lang.Object.toString(), public native int java.lang.Object.hashCode(), public final native java.lang.Class java.lang.Object.getClass(), protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException, public final native void java.lang.Object.notify(), public final native void java.lang.Object.notifyAll(), public void Foo$Bar.bar(java.lang.String,java.lang.Integer)] allows for delegation from public java.lang.Void net.bytebuddy.renamed.java.lang.Object$ByteBuddy$P87HQ3lQ.bar(java.lang.String,java.lang.Integer)
at net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor.process(MethodDelegationBinder.java:881)
at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1218)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:510)
at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:444)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:3193)
at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1481)
at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:234)
at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$AbstractDelegatingBuilder.make(DynamicType.java:2177)
at Foo.main(Foo.java:55)

最奇怪的部分是在异常消息的最后:

[...] public void Foo$Bar.bar(java.lang.String,java.lang.Integer)] allows for delegation from public java.lang.Void net.bytebuddy.renamed.java.lang.Object$ByteBuddy$P87HQ3lQ.bar(java.lang.String,java.lang.Integer)

我究竟做错了什么?

4

2 回答 2

2

你的假设是对的。Byte Buddy 不能将void非类型分配给Void类型。但是,当您使用以下命令注释拦截器时, Byte Buddy 可以null从 void 方法分配给引用类型@RuntimeType

public class Bar {
  @RuntimeType
  public void bar (String s, Integer i) {
    System.out.println ("s:" + s + " i:" + i);
  }
}
public class Baz {
  @RuntimeType
  public void baz (Integer i, String s) {
    System.out.println ("i:" + i + " s:" + s);
  }
}
于 2016-01-08T07:54:05.563 回答
0

当我提交并回顾我的问题时,我认为问题可能出在void返回而不是Void确实如此,更改拦截器上的返回类型有效

于 2016-01-07T16:16:43.020 回答