int identifierNo = identifierCount++;
String fieldName = METHOD_FIELD_PREFIX + identifierNo;
classFile.addField(AccessFlag.PRIVATE | AccessFlag.STATIC, fieldName, Method.class);
methodIdentifiers.put(methodToLoad, fieldName);
// we need to create the method in the static constructor
CodeAttribute ca = staticConstructor.getCodeAttribute();
// we need to call getDeclaredMethods and then iterate
ca.loadClass(methodToLoad.getDeclaringClass().getName());
ca.invokevirtual("java.lang.Class", "getDeclaredMethods", "()[Ljava/lang/reflect/Method;");
ca.dup();
ca.arraylength();
ca.dup();
ca.istore(0);
ca.aconstNull();
ca.astore(1);
ca.aconstNull();
ca.astore(2);
ca.aconstNull();
ca.astore(3);
// so here we have the array index on top of the stack, followed by the array
CodeLocation loopBegin = ca.mark();
BranchEnd loopEnd = ca.ifeq();
ca.dup();
ca.iinc(0, -1);
ca.iload(0); // load the array index into the stack
ca.dupX1(); // index, array, index, array
ca.aaload();
ca.checkcast("java.lang.reflect.Method");
ca.dup();
ca.astore(2); // Method, index, array
// compare method names
ca.invokevirtual("java.lang.reflect.Method", "getName", "()Ljava/lang/String;");
ca.ldc(methodToLoad.getName());
ca.invokevirtual("java.lang.Object", "equals", "(Ljava/lang/Object;)Z"); // int,index,array
ca.ifEq(loopBegin);
// compare return types
ca.aload(2);
ca.invokevirtual("java.lang.reflect.Method", "getReturnType", "()Ljava/lang/Class;");
ca.loadType(DescriptorUtils.makeDescriptor(methodToLoad.getReturnType()));
ca.invokevirtual("java.lang.Object", "equals", "(Ljava/lang/Object;)Z"); // int,index,array
ca.ifEq(loopBegin);
// load the method parameters
Class<?>[] parameters = methodToLoad.getParameterTypes();
ca.aload(2);
ca.invokevirtual("java.lang.reflect.Method", "getParameterTypes", "()[Ljava/lang/Class;");
ca.dup();
ca.astore(3);
ca.arraylength();
ca.iconst(parameters.length);
ca.ifIcmpne(loopBegin); // compare parameter array length
for (int i = 0; i < parameters.length; ++i) {
ca.aload(3);
ca.iconst(i);
ca.aaload();
ca.loadType(DescriptorUtils.makeDescriptor(parameters[i]));
ca.invokevirtual("java.lang.Object", "equals", "(Ljava/lang/Object;)Z"); // int,index,array
ca.ifEq(loopBegin);
}
ca.pop();
BranchEnd gotoEnd = ca.gotoInstruction(); // we have found the method, goto the pointwhere we write it to a static
// field
// throw runtime exception as we could not find the method.
// this will only happen if the proxy isloaded into the wrong classloader
ca.branchEnd(loopEnd);
ca.newInstruction("java.lang.RuntimeException");
ca.dup();
ca.ldc("Could not find method " + methodToLoad);
ca.invokespecial("java.lang.RuntimeException", "<init>", "(Ljava/lang/String;)V");
ca.athrow();
ca.branchEnd(gotoEnd);
ca.pop();
ca.aload(2);
ca.checkcast("java.lang.reflect.Method");
ca.putstatic(getClassName(), fieldName, METHOD_FIELD_DESCRIPTOR);
}
String fieldName = methodIdentifiers.get(methodToLoad);
method.getCodeAttribute().getstatic(getClassName(), fieldName, METHOD_FIELD_DESCRIPTOR);
}