Reputation: 1305
I would like to generate follwing method with bytebuddy stackmanipulation.
public void test() {
this.process(() -> {
System.out.println("Im lambda call");
}
}
if such code would be compiled with javac it would produce:
If i had just ASM i could do something like this
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitInvokeDynamicInsn("run", "(LmyTest/Test;)Ljava/lang/Runnable;", new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;", false), new Object[]{Type.getType("()V"), new Handle(Opcodes.H_INVOKESPECIAL, "myTest/Test", "lambda$test$0", "()V", false), Type.getType("()V")});
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, process ....)
How would i do this with just bytebuddy? Im using bytebuddy as its abstraction over opcodes is just much more pleasant to write than raw asm.
Let`s assume that the content of Runnable (method call of lambda$test$0) has already been generated
MethodDescription.InDefinedShape targetCall = thisType.getDeclaredMethods().filter(named("lambda$test$0")).getOnly();
InvokeDynamic methodRef = InvokeDynamic.lambda(targetCall, new TypeDescription.ForLoadedType(Runnable.class)).withoutArguments();
StackManipulation.Size size = new StackManipulation.Compound(
stackManipulations...
methodRef... ??
).apply(mv, ctx);
This is where i dont know what to do. How can i get StackManipulation from InvokeDynamic?
Upvotes: 3
Views: 318
Reputation: 44032
To create a stack manipulation for a dynamic method invocation, instead of InvokeDynamic
(a more high level Implementation
), use
MethodInvocation.invoke(targetCall).dynamic("run",
Collections.singletonList(thisType),
TypeDescription.ForLoadedType.of(Runnable.class),
Collections.emptyList());
You can chain this StackManipulation
with the rest of your code.
In this case, ASM might however not be the worst option, it is a rather good byte code emitter and Byte Buddy does therefore not attempt to reimplement it. If it is the least amount of code, you can wrap it in a stack manipulation and implement the method using it, too, if this is an option you consider.
Upvotes: 3