/** * Gets the correct return instruction for a proxy method * * @param pool * @param methodDescriptor */ public static void addReturnProxyMethod(String methodDescriptor, Bytecode b) { String ret = DescriptorUtils.getReturnType(methodDescriptor); // if the return type is larger than one then it is not a primitive // so just do an ARETURN if (ret.length() != 1) { b.addCheckcast(DescriptorUtils.getReturnTypeInJvmFormat(methodDescriptor)); b.add(Opcode.ARETURN); return; } // void methods are special if (ret.equals("V")) { b.add(Opcode.RETURN); return; } else { // unbox the primitive type char tp = ret.charAt(0); Boxing.unbox(b, tp); if (tp == 'F') { b.add(Opcode.FRETURN); } else if (tp == 'D') { b.add(Opcode.DRETURN); } else if (tp == 'J') { b.add(Opcode.LRETURN); } else { b.add(Opcode.IRETURN); } return; } }
/** Add a method to a class that simply delegates to the parent implementation of the method */ public static void addDelegatingMethod(ClassFile file, MethodData mData) throws BadBytecode, DuplicateMemberException { MethodInfo m = new MethodInfo(file.getConstPool(), mData.getMethodName(), mData.getDescriptor()); m.setAccessFlags(mData.getAccessFlags()); Bytecode code = new Bytecode(file.getConstPool()); String[] params = DescriptorUtils.descriptorStringToParameterArray(mData.getDescriptor()); code.add(Opcode.ALOAD_0); // push this int count = 1; // zero is the this pointer int maxLocals = 1; for (String p : params) { // int char short boolean byte if (p.equals("I") || p.equals("C") || p.equals("S") || p.equals("Z") || p.equals("B")) { // push integer 0 code.addIload(count); maxLocals++; } // long else if (p.equals("J")) { code.addLload(count); maxLocals += 2; count++; } // double else if (p.equals("D")) { code.addDload(count); maxLocals += 2; count++; } // float else if (p.equals("F")) { code.addFload(count); maxLocals++; } // arrays and reference types else { code.addAload(count); maxLocals++; } count++; } code.addInvokespecial(file.getSuperclass(), mData.getMethodName(), mData.getDescriptor()); String p = DescriptorUtils.getReturnTypeInJvmFormat(mData.getDescriptor()); // int char short boolean byte if (p.equals("I") || p.equals("C") || p.equals("S") || p.equals("Z") || p.equals("B")) { code.add(Opcode.IRETURN); } // long else if (p.equals("J")) { code.add(Opcode.LRETURN); } // double else if (p.equals("D")) { code.add(Opcode.DRETURN); } // float else if (p.equals("F")) { code.add(Opcode.FRETURN); } // void else if (p.equals("V")) { code.add(Opcode.RETURN); } // arrays and reference types else { code.add(Opcode.ARETURN); } CodeAttribute ca = code.toCodeAttribute(); ca.computeMaxStack(); ca.setMaxLocals(maxLocals); m.setCodeAttribute(ca); file.addMethod(m); }