package me.tomassetti.bytecode_generation; import me.tomassetti.jvm.JvmMethodDefinition; import org.objectweb.asm.MethodVisitor; import static org.objectweb.asm.Opcodes.*; public class MethodInvocationBS extends BytecodeSequence { private JvmMethodDefinition jvmMethodDefinition; public MethodInvocationBS(JvmMethodDefinition jvmMethodDefinition) { this.jvmMethodDefinition = jvmMethodDefinition; } @Override public void operate(MethodVisitor mv) { // The difference between the invokespecial and the invokevirtual instructions is that invokevirtual invokes // a method based on the class of the object. The invokespecial instruction is used to invoke instance // initialization methods as well as private methods and methods of a superclass of the current class. // ref.: http://zeroturnaround.com/rebellabs/java-bytecode-fundamentals-using-objects-and-calling-methods/ if (jvmMethodDefinition.isStatic()) { mv.visitMethodInsn(INVOKESTATIC, jvmMethodDefinition.getOwnerInternalName(), jvmMethodDefinition.getName(), jvmMethodDefinition.getDescriptor(), false); } else { if (jvmMethodDefinition.isDeclaredOnInterface()) { mv.visitMethodInsn(INVOKEINTERFACE, jvmMethodDefinition.getOwnerInternalName(), jvmMethodDefinition.getName(), jvmMethodDefinition.getDescriptor(), true); } else { mv.visitMethodInsn(INVOKEVIRTUAL, jvmMethodDefinition.getOwnerInternalName(), jvmMethodDefinition.getName(), jvmMethodDefinition.getDescriptor(), false); } } } }