⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 proxy.java

📁 gcc的组建
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
      return data;    }  } // class ProxyData  /**   * Does all the work of building a class. By making this a nested class,   * this code is not loaded in memory if the VM has a native   * implementation instead.   *   * @author Eric Blake (ebb9@email.byu.edu)   */  private static final class ClassFactory  {    /** Constants for assisting the compilation */    private static final byte FIELD = 1;    private static final byte METHOD = 2;    private static final byte INTERFACE = 3;    private static final String CTOR_SIG      = "(Ljava/lang/reflect/InvocationHandler;)V";    private static final String INVOKE_SIG = "(Ljava/lang/Object;"      + "Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;";    /** Bytecodes for insertion in the class definition byte[] */    private static final char ACONST_NULL = 1;    private static final char ICONST_0 = 3;    private static final char BIPUSH = 16;    private static final char SIPUSH = 17;    private static final char ILOAD = 21;    private static final char ILOAD_0 = 26;    private static final char ALOAD_0 = 42;    private static final char ALOAD_1 = 43;    private static final char AALOAD = 50;    private static final char AASTORE = 83;    private static final char DUP = 89;    private static final char DUP_X1 = 90;    private static final char SWAP = 95;    private static final char IRETURN = 172;    private static final char LRETURN = 173;    private static final char FRETURN = 174;    private static final char DRETURN = 175;    private static final char ARETURN = 176;    private static final char RETURN = 177;    private static final char GETSTATIC = 178;    private static final char GETFIELD = 180;    private static final char INVOKEVIRTUAL = 182;    private static final char INVOKESPECIAL = 183;    private static final char INVOKEINTERFACE = 185;    private static final char NEW = 187;    private static final char ANEWARRAY = 189;    private static final char ATHROW = 191;    private static final char CHECKCAST = 192;    // Implementation note: we use StringBuffers to hold the byte data, since    // they automatically grow.  However, we only use the low 8 bits of    // every char in the array, so we are using twice the necessary memory    // for the ease StringBuffer provides.    /** The constant pool. */    private final StringBuffer pool = new StringBuffer();    /** The rest of the class data. */    private final StringBuffer stream = new StringBuffer();    /** Map of strings to byte sequences, to minimize size of pool. */    private final Map poolEntries = new HashMap();    /** The VM name of this proxy class. */    private final String qualName;    /**     * The Method objects the proxy class refers to when calling the     * invocation handler.     */    private final Method[] methods;    /**     * Initializes the buffers with the bytecode contents for a proxy class.     *     * @param data the remainder of the class data     * @throws IllegalArgumentException if anything else goes wrong this     *         late in the game; as far as I can tell, this will only happen     *         if the constant pool overflows, which is possible even when     *         the user doesn't exceed the 65535 interface limit     */    ClassFactory(ProxyData data)    {      methods = data.methods;      // magic = 0xcafebabe      // minor_version = 0      // major_version = 46      // constant_pool_count: place-holder for now      pool.append("\u00ca\u00fe\u00ba\u00be\0\0\0\56\0\0");      // constant_pool[], filled in as we go      // access_flags      putU2(Modifier.SUPER | Modifier.FINAL | Modifier.PUBLIC);      // this_class      qualName = (data.pack + "$Proxy" + data.id);      putU2(classInfo(TypeSignature.getEncodingOfClass(qualName, false)));      // super_class      putU2(classInfo("java/lang/reflect/Proxy"));      // interfaces_count      putU2(data.interfaces.length);      // interfaces[]      for (int i = 0; i < data.interfaces.length; i++)        putU2(classInfo(data.interfaces[i]));      // Recall that Proxy classes serialize specially, so we do not need      // to worry about a <clinit> method for this field.  Instead, we      // just assign it by reflection after the class is successfully loaded.      // fields_count - private static Method[] m;      putU2(1);      // fields[]      // m.access_flags      putU2(Modifier.PRIVATE | Modifier.STATIC);      // m.name_index      putU2(utf8Info("m"));      // m.descriptor_index      putU2(utf8Info("[Ljava/lang/reflect/Method;"));      // m.attributes_count      putU2(0);      // m.attributes[]      // methods_count - # handler methods, plus <init>      putU2(methods.length + 1);      // methods[]      // <init>.access_flags      putU2(Modifier.PUBLIC);      // <init>.name_index      putU2(utf8Info("<init>"));      // <init>.descriptor_index      putU2(utf8Info(CTOR_SIG));      // <init>.attributes_count - only Code is needed      putU2(1);      // <init>.Code.attribute_name_index      putU2(utf8Info("Code"));      // <init>.Code.attribute_length = 18      // <init>.Code.info:      //   $Proxynn(InvocationHandler h) { super(h); }      // <init>.Code.max_stack = 2      // <init>.Code.max_locals = 2      // <init>.Code.code_length = 6      // <init>.Code.code[]      stream.append("\0\0\0\22\0\2\0\2\0\0\0\6" + ALOAD_0 + ALOAD_1                    + INVOKESPECIAL);      putU2(refInfo(METHOD, "java/lang/reflect/Proxy", "<init>", CTOR_SIG));      // <init>.Code.exception_table_length = 0      // <init>.Code.exception_table[]      // <init>.Code.attributes_count = 0      // <init>.Code.attributes[]      stream.append(RETURN + "\0\0\0\0");      for (int i = methods.length - 1; i >= 0; i--)        emitMethod(i, data.exceptions[i]);      // attributes_count      putU2(0);      // attributes[] - empty; omit SourceFile attribute      // XXX should we mark this with a Synthetic attribute?    }    /**     * Produce the bytecode for a single method.     *     * @param i the index of the method we are building     * @param e the exceptions possible for the method     */    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)        {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -