Search code examples
byte-buddy

Can I compose an InvokeDynamic with a FixedValue using Implementation.Composable#andThen()?


I am building a method "by hand" in ByteBuddy. The method I'm building has one parameter of type ProductType. Let's say it looks like this:

public ProductType frob(ProductType product) {
  // stuff that I'm implementing and asking about goes here
}

Inside that method I am building the equivalent of:

product.foo(); // more on this below; foo() has a void return type, which may be important
return product; // FixedValue.argument(0)

This works fine when I build an Implementation like this:

MethodCall.invoke(fooMethodDescription) // invoke foo()...
  .onArgument(0) // ...on product...
  .andThen(FixedValue.argument(0)); // ...and then return product

(I hope I've typed that right.)

If, however, I build an Implementation like this:

InvokeDynamic.bootstrap(...) // look up foo()'s MethodHandle via my bootstrap method...
  .invoke("foo", TypeDescription.VOID) // ...invoke the method handle with a return type of void...
  .withArgument(0) // ..."on" the first and only argument (product) and "with" no other arguments...
  .andThen(FixedValue.argument(0)); // ...and then return product

…with, of course, the proper InvokeDynamic recipe, the resulting class cannot be verified because of an Operand stack underflow error (Attempt to pop empty stack).

I have a similar InvokeDynamic recipe used many places elsewhere so I know that my problem is not with the InvokeDynamic usage. Rather, it seems to be with the composing? maybe? Is it possible that MethodCall and InvokeDynamic behave differently, even though both are Implementations? Maybe InvokeDynamic doesn't push something on the operand stack (maybe just in the case of void returns?) whereas MethodCall does? Is there something I'm missing in the andThen() usage?

Using ByteBuddy 1.11.2.


Solution

  • As you pointed out correctly, this is a bug in Byte Buddy that is now fixed. Thanks for that. It will be released with version 1.11.3.