用于将新创建的对象传递给方法的字节伙伴代码

问题描述 投票:1回答:1

所以,我试图用Byte Buddy生成一些相对简单的代码,但我一直遇到异常。

[基本上,我试图让Byte Buddy(版本1.9.0)生成与以下Java类等效的东西(这只是一个简化的示例;通常在尝试将新创建的对象传递给方法时会发生此问题) :

public class CalendarSetter
{
  public void setCalendarTime(Calendar calendar)
  {
    calendar.setTime(new Date());
  }
}

我想出的字节伙伴代码如下(使用Xtend语法,但是非常接近Java:]

  val Builder<?> builder = new ByteBuddy()
    .subclass(Object).name("CalendarSetter").merge(Visibility.PUBLIC)
    .defineMethod("setCalendarTime", void, Visibility.PUBLIC)
    .withParameter(Calendar)
    .intercept(MethodCall.invoke(new ForLoadedMethod(Calendar.getDeclaredMethod("setTime", Date)))
      .onArgument(0)
      .withMethodCall(MethodCall.construct(Date.getConstructor)))
  builder.make.load(class.classLoader).loaded

不幸的是,这只会产生以下异常:

java.lang.IllegalStateException: Cannot assign public java.util.Date() to java.util.Date arg0
    at net.bytebuddy.implementation.MethodCall$ArgumentLoader$ForMethodCall.resolve(MethodCall.java:1470)
    at net.bytebuddy.implementation.MethodCall.toStackManipulation(MethodCall.java:2397)
    at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:2434)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:698)
    ...

[调试器中的一些进一步说明表明,这是由于Date的构造函数(像所有构造函数一样)的返回类型为void,而返回类型又与java.util.Date不兼容。字节伙伴的VoidAwareAssigner产生非法的StackManipulation,因为源类型为void,而目标类型为非void,并且Typing不是动态的。我希望VoidAwareAssigner确实应该意识到构造函数实际上是void方法,但是我可能在这里缺少其他内容。

将新创建的对象作为字节伙伴中的方法参数传递的正确方法是什么?

UPDATE:通过将.withAssigner(custom, Typing.DYNAMIC)与始终返回Assigner的自定义“平凡” StackManipulation.Trivial相加,可以避免出现异常。此替代方法可产生看似正确(且有效)的字节码:

public class CalendarSetter {
  public void setCalendarTime(java.util.Calendar);
    Code:
       0: aload_1
       1: new           #8                  // class java/util/Date
       4: dup
       5: invokespecial #12                 // Method java/util/Date."<init>":()V
       8: invokevirtual #18                 // Method java/util/Calendar.setTime:(Ljava/util/Date;)V
      11: return
...

但是我仍然觉得这不是真正正确的方法,可能会简化一些我不知道的场景...

java jvm byte-buddy jvm-bytecode
1个回答
0
投票

您发现了一个我刚刚在master分支上修复的错误。它将是1.10.12版本的一部分。

[字节伙伴]错误地将构造函数的返回类型解析为void。

© www.soinside.com 2019 - 2024. All rights reserved.