else if (ret_type.isPrimitive()) {
} else if (ret_type.isPrimitive()) {
    private void emitMethod(int i, Class[] e)    {            // First, we precalculate the method length and other information.      Method m = methods[i];            Class[] paramtypes = m.getParameterTypes();            int wrap_overhead = 0; // max words taken by wrapped primitive            int param_count = 1; // 1 for this      int code_length = 16; // aload_0, getfield, aload_0, getstatic, const,            // aaload, const/aconst_null, invokeinterface      if (i > 5)        {                if (i > Byte.MAX_VALUE)                    code_length += 2; // sipush                else                    code_length++; // bipush            }      if (paramtypes.length > 0)        {                code_length += 3; // anewarray                if (paramtypes.length > Byte.MAX_VALUE)                    code_length += 2; // sipush          else if (paramtypes.length > 5)            code_length++; // bipush          for (int j = 0; j < paramtypes.length; j++)            {                    code_length += 4; // dup, const, load, store              Class type = paramtypes[j];              if (j > 5)                {                        if (j > Byte.MAX_VALUE)                            code_length += 2; // sipush                        else                            code_length++; // bipush                    }              if (param_count >= 4)                code_length++; // 2-byte load                    param_count++;              if (type.isPrimitive())                {                        code_length += 7; // new, dup, invokespecial                  if (type == long.class || type == double.class)                    {                            wrap_overhead = 3;                            param_count++;                    }                  else if (wrap_overhead < 2)                    wrap_overhead = 2;                    }                }            }            int end_pc = code_length;            Class ret_type = m.getReturnType();            if (ret_type == void.class)                code_length++; // return            else if (ret_type.isPrimitive())                code_length += 7; // cast, invokevirtual, return            else                code_length += 4; // cast, return            int exception_count = 0;            boolean throws_throwable = false;            for (int j = 0; j < e.length; j++)        if (e[j] == Throwable.class)          {                    throws_throwable = true;                    break;                }      if (! throws_throwable)        {          exception_count = e.length + 3; // Throwable, Error, RuntimeException                code_length += 9; // new, dup_x1, swap, invokespecial, athrow            }            int handler_pc = code_length - 1;            StringBuffer signature = new StringBuffer("(");            for (int j = 0; j < paramtypes.length; j++)        signature.append(TypeSignature.getEncodingOfClass(paramtypes[j]));      signature.append(")").append(TypeSignature.getEncodingOfClass(ret_type));            // Now we have enough information to emit the method.            // handler.access_flags            putU2(Modifier.PUBLIC | Modifier.FINAL);            // handler.name_index            putU2(utf8Info(m.getName()));            // handler.descriptor_index            putU2(utf8Info(signature.toString()));            // handler.attributes_count - Code is necessary, Exceptions possible            putU2(e.length > 0 ? 2 : 1);            // handler.Code.info:            //   type name(args) {            //     try {            //       return (type) h.invoke(this, methods[i], new Object[] {args});            //     } catch (<declared Exceptions> e) {            //       throw e;            //     } catch (Throwable t) {            //       throw new UndeclaredThrowableException(t);            //     }            //   }            // Special cases:            //  if arg_n is primitive, wrap it            //  if method throws Throwable, try-catch is not needed            //  if method returns void, return statement not needed            //  if method returns primitive, unwrap it            //  save space by sharing code for all the declared handlers            // handler.Code.attribute_name_index            putU2(utf8Info("Code"));            // handler.Code.attribute_length            putU4(12 + code_length + 8 * exception_count);            // handler.Code.max_stack            putU2(param_count == 1 ? 4 : 7 + wrap_overhead);            // handler.Code.max_locals            putU2(param_count);            // handler.Code.code_length            putU4(code_length);            // handler.Code.code[]            putU1(ALOAD_0);            putU1(GETFIELD);            putU2(refInfo(FIELD, "java/lang/reflect/Proxy", "h",                    "Ljava/lang/reflect/InvocationHandler;"));            putU1(ALOAD_0);            putU1(GETSTATIC);      putU2(refInfo(FIELD, TypeSignature.getEncodingOfClass(qualName, false),                    "m", "[Ljava/lang/reflect/Method;"));            putConst(i);            putU1(AALOAD);      if (paramtypes.length > 0)        {                putConst(paramtypes.length);                putU1(ANEWARRAY);                putU2(classInfo("java/lang/Object"));                param_count = 1;          for (int j = 0; j < paramtypes.length; j++, param_count++)            {                    putU1(DUP);                    putConst(j);              if (paramtypes[j].isPrimitive())                {                        putU1(NEW);                  putU2(classInfo(wrapper(paramtypes[j])));                        putU1(DUP);                    }              putLoad(param_count, paramtypes[j]);              if (paramtypes[j].isPrimitive())                {                        putU1(INVOKESPECIAL);                  putU2(refInfo(METHOD, wrapper(paramtypes[j]), "<init>",                                '(' + (TypeSignature                                       .getEncodingOfClass(paramtypes[j])                                       + ")V")));                  if (paramtypes[j] == long.class                      || paramtypes[j] == double.class)                                param_count++;                    }                    putU1(AASTORE);                }        }      else                putU1(ACONST_NULL);            putU1(INVOKEINTERFACE);            putU2(refInfo(INTERFACE, "java/lang/reflect/InvocationHandler",                    "invoke", INVOKE_SIG));            putU1(4); // InvocationHandler, this, Method, Object[]            putU1(0);            if (ret_type == void.class)                putU1(RETURN);      else if (ret_type.isPrimitive())        {                putU1(CHECKCAST);                putU2(classInfo(wrapper(ret_type)));                putU1(INVOKEVIRTUAL);          putU2(refInfo(METHOD, wrapper(ret_type),                        ret_type.getName() + "Value",                        "()" + TypeSignature.getEncodingOfClass(ret_type)));                if (ret_type == long.class)                    putU1(LRETURN);                else if (ret_type == float.class)                    putU1(FRETURN);                else if (ret_type == double.class)                    putU1(DRETURN);                else                    putU1(IRETURN);        }      else        {                putU1(CHECKCAST);                putU2(classInfo(ret_type));                putU1(ARETURN);            }      if (! throws_throwable)        {                putU1(NEW);                putU2(classInfo("java/lang/reflect/UndeclaredThrowableException"));                putU1(DUP_X1);                putU1(SWAP);                putU1(INVOKESPECIAL);                putU2(refInfo(METHOD,                        "java/lang/reflect/UndeclaredThrowableException",                        "<init>", "(Ljava/lang/Throwable;)V"));                putU1(ATHROW);            }            // handler.Code.exception_table_length            putU2(exception_count);            // handler.Code.exception_table[]      if (! throws_throwable)        {                // handler.Code.exception_table.start_pc                putU2(0);                // handler.Code.exception_table.end_pc                putU2(end_pc);                // handler.Code.exception_table.handler_pc                putU2(handler_pc);                // handler.Code.exception_table.catch_type                putU2(classInfo("java/lang/Error"));                // handler.Code.exception_table.start_pc                putU2(0);                // handler.Code.exception_table.end_pc                putU2(end_pc);                // handler.Code.exception_table.handler_pc                putU2(handler_pc);                // handler.Code.exception_table.catch_type                putU2(classInfo("java/lang/RuntimeException"));          for (int j = 0; j < e.length; j++)            {                    // handler.Code.exception_table.start_pc                    putU2(0);                    // handler.Code.exception_table.end_pc                    putU2(end_pc);                    // handler.Code.exception_table.handler_pc                    putU2(handler_pc);                    // handler.Code.exception_table.catch_type              putU2(classInfo(e[j]));                }                // handler.Code.exception_table.start_pc                putU2(0);                // handler.Code.exception_table.end_pc                putU2(end_pc);                // handler.Code.exception_table.handler_pc -                //   -8 for undeclared handler, which falls thru to normal one                putU2(handler_pc - 8);                // handler.Code.exception_table.catch_type                putU2(0);            }            // handler.Code.attributes_count            putU2(0);            // handler.Code.attributes[]      if (e.length > 0)        {                // handler.Exceptions.attribute_name_index                putU2(utf8Info("Exceptions"));                // handler.Exceptions.attribute_length                putU4(2 * e.length + 2);                // handler.Exceptions.number_of_exceptions                putU2(e.length);                // handler.Exceptions.exception_index_table[]                for (int j = 0; j < e.length; j++)            putU2(classInfo(e[j]));            }        }