// push our parameter values into the array
// invokeinterface the invoke method
// add checkcast to cast the result to the return type, or unbox if
// primitive
// add an appropriate return instruction
final CodeAttribute b = classMethod.getCodeAttribute();
b.aload(0);
b.getfield(classMethod.getClassFile().getName(), METHOD_HANDLER_FIELD_NAME, DescriptorUtils.classToStringRepresentation(MethodHandler.class));
b.aload(0);
bytecodeMethodResolver.getDeclaredMethod(classMethod, method.getDeclaringClass(), method.getName(), method.getParameterTypes(), staticConstructor);
b.aconstNull();
b.iconst(method.getParameterTypes().length);
b.anewarray("java.lang.Object");
int localVariableCount = 1;
for (int i = 0; i < method.getParameterTypes().length; ++i) {
String typeString = method.getParameterTypes()[i];
b.dup(); // duplicate the array reference
b.iconst(i);
// load the parameter value
BytecodeUtils.addLoadInstruction(b, typeString, localVariableCount);
// box the parameter if necessary
Boxing.boxIfNecessary(b, typeString);
// and store it in the array
b.aastore();
if (DescriptorUtils.isWide(typeString)) {
localVariableCount = localVariableCount + 2;
} else {
localVariableCount++;
}
}
// now we have all our arguments on the stack
// lets invoke the method
b.invokeinterface(MethodHandler.class.getName(), "invoke", LJAVA_LANG_OBJECT, new String[] { LJAVA_LANG_OBJECT,
LJAVA_LANG_REFLECT_METHOD, LJAVA_LANG_REFLECT_METHOD, "[" + LJAVA_LANG_OBJECT });
if (addReturnInstruction) {
// now we need to return the appropriate type
if (method.getReturnType().equals(DescriptorUtils.VOID_CLASS_DESCRIPTOR)) {
b.returnInstruction();
} else if(DescriptorUtils.isPrimitive(method.getReturnType())) {
Boxing.unbox(b, method.getReturnType());
b.returnInstruction();
} else {
String castType = method.getReturnType();
if (!method.getReturnType().startsWith("[")) {
castType = method.getReturnType().substring(1).substring(0, method.getReturnType().length() - 2);
}
b.checkcast(castType);
b.returnInstruction();
}
}
}