tbo*_*odt 39
代理是在运行时创建和加载的类.这些类没有源代码.我知道你想知道如何让他们做一些事情,如果有没有为他们的代码.答案是,当你创建它们,你指定实现目标InvocationHandler,这是定义调用的代理方法时调用的方法.
您可以使用该调用创建它们
Proxy.newProxyInstance(classLoader, interfaces, invocationHandler)
论点是:
classLoader.生成类后,将使用此类加载器加载它.interfaces.必须全部是接口的类对象数组.生成的代理实现所有这些接口.invocationHandler.这是您的代理在调用方法时知道该怎么做的方式.它是一个实现的对象InvocationHandler.当从任何支持的接口的方法,或hashCode,equals或toString,被调用,该方法invoke调用的处理程序中,经过Method用于向被调用的方法和传递的参数对象.有关详细信息,请参阅该Proxy课程的文档.
版本1.3之后的每个JVM实现都必须支持这些.它们被加载到具体实现的方式JVM的内部数据结构,但它是保证工作.
far*_*992 39
没什么特别的.与普通Java类实例一样.
但那些课是Synthetic proxy classes由java.lang.reflect.Proxy#newProxyInstance
1.3中介绍
http://docs.oracle.com/javase/1.3/docs/relnotes/features.html#reflection
它是Java的一部分.所以每个JVM都应该支持它.
简而言之:它们是使用JVM ASM技术创建的(在运行时定义javabyte代码)
使用相同技术的东西:
java.lang.reflect.Proxy#newProxyInstancegetProxyClass0以获取`类
  `
ProxyGenerator.generateProxyClass返回字节[] 的魔法define class来加载生成的$ProxyClass(你看到的类名)每个方法都使用相同的字节码构建
invocation handler'sinvoke()invocation handler's 获得返回值invoke()类(字节码)以形式表示 byte[]
如何画一个班级
认为你的java代码被编译成字节码,只需在运行时执行此操作即可
sun/misc/ProxyGenerator.java中的核心方法
generateClassFile
/**
 * Generate a class file for the proxy class.  This method drives the
 * class file generation process.
 */
private byte[] generateClassFile() {
    /* ============================================================
     * Step 1: Assemble ProxyMethod objects for all methods to
     * generate proxy dispatching code for.
     */
    /*
     * Record that proxy methods are needed for the hashCode, equals,
     * and toString methods of java.lang.Object.  This is done before
     * the methods from the proxy interfaces so that the methods from
     * java.lang.Object take precedence over duplicate methods in the
     * proxy interfaces.
     */
    addProxyMethod(hashCodeMethod, Object.class);
    addProxyMethod(equalsMethod, Object.class);
    addProxyMethod(toStringMethod, Object.class);
    /*
     * Now record all of the methods from the proxy interfaces, giving
     * earlier interfaces precedence over later ones with duplicate
     * methods.
     */
    for (int i = 0; i < interfaces.length; i++) {
        Method[] methods = interfaces[i].getMethods();
        for (int j = 0; j < methods.length; j++) {
            addProxyMethod(methods[j], interfaces[i]);
        }
    }
    /*
     * For each set of proxy methods with the same signature,
     * verify that the methods' return types are compatible.
     */
    for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
        checkReturnTypes(sigmethods);
    }
    /* ============================================================
     * Step 2: Assemble FieldInfo and MethodInfo structs for all of
     * fields and methods in the class we are generating.
     */
    try {
        methods.add(generateConstructor());
        for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
            for (ProxyMethod pm : sigmethods) {
                // add static field for method's Method object
                fields.add(new FieldInfo(pm.methodFieldName,
                    "Ljava/lang/reflect/Method;",
                     ACC_PRIVATE | ACC_STATIC));
                // generate code for proxy method and add it
                methods.add(pm.generateMethod());
            }
        }
        methods.add(generateStaticInitializer());
    } catch (IOException e) {
        throw new InternalError("unexpected I/O Exception");
    }
    if (methods.size() > 65535) {
        throw new IllegalArgumentException("method limit exceeded");
    }
    if (fields.size() > 65535) {
        throw new IllegalArgumentException("field limit exceeded");
    }
    /* ============================================================
     * Step 3: Write the final class file.
     */
    /*
     * Make sure that constant pool indexes are reserved for the
     * following items before starting to write the final class file.
     */
    cp.getClass(dotToSlash(className));
    cp.getClass(superclassName);
    for (int i = 0; i < interfaces.length; i++) {
        cp.getClass(dotToSlash(interfaces[i].getName()));
    }
    /*
     * Disallow new constant pool additions beyond this point, since
     * we are about to write the final constant pool table.
     */
    cp.setReadOnly();
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    DataOutputStream dout = new DataOutputStream(bout);
    try {
        /*
         * Write all the items of the "ClassFile" structure.
         * See JVMS section 4.1.
         */
                                    // u4 magic;
        dout.writeInt(0xCAFEBABE);
                                    // u2 minor_version;
        dout.writeShort(CLASSFILE_MINOR_VERSION);
                                    // u2 major_version;
        dout.writeShort(CLASSFILE_MAJOR_VERSION);
        cp.write(dout);             // (write constant pool)
                                    // u2 access_flags;
        dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
                                    // u2 this_class;
        dout.writeShort(cp.getClass(dotToSlash(className)));
                                    // u2 super_class;
        dout.writeShort(cp.getClass(superclassName));
                                    // u2 interfaces_count;
        dout.writeShort(interfaces.length);
                                    // u2 interfaces[interfaces_count];
        for (int i = 0; i < interfaces.length; i++) {
            dout.writeShort(cp.getClass(
                dotToSlash(interfaces[i].getName())));
        }
                                    // u2 fields_count;
        dout.writeShort(fields.size());
                                    // field_info fields[fields_count];
        for (FieldInfo f : fields) {
            f.write(dout);
        }
                                    // u2 methods_count;
        dout.writeShort(methods.size());
                                    // method_info methods[methods_count];
        for (MethodInfo m : methods) {
            m.write(dout);
        }
                                     // u2 attributes_count;
        dout.writeShort(0); // (no ClassFile attributes for proxy classes)
    } catch (IOException e) {
        throw new InternalError("unexpected I/O Exception");
    }
    return bout.toByteArray();
}
addProxyMethod
/**
 * Add another method to be proxied, either by creating a new
 * ProxyMethod object or augmenting an old one for a duplicate
 * method.
 *
 * "fromClass" indicates the proxy interface that the method was
 * found through, which may be different from (a subinterface of)
 * the method's "declaring class".  Note that the first Method
 * object passed for a given name and descriptor identifies the
 * Method object (and thus the declaring class) that will be
 * passed to the invocation handler's "invoke" method for a given
 * set of duplicate methods.
 */
private void addProxyMethod(Method m, Class fromClass) {
    String name = m.getName();
    Class[] parameterTypes = m.getParameterTypes();
    Class returnType = m.getReturnType();
    Class[] exceptionTypes = m.getExceptionTypes();
    String sig = name + getParameterDescriptors(parameterTypes);
    List<ProxyMethod> sigmethods = proxyMethods.get(sig);
    if (sigmethods != null) {
        for (ProxyMethod pm : sigmethods) {
            if (returnType == pm.returnType) {
                /*
                 * Found a match: reduce exception types to the
                 * greatest set of exceptions that can thrown
                 * compatibly with the throws clauses of both
                 * overridden methods.
                 */
                List<Class<?>> legalExceptions = new ArrayList<Class<?>>();
                collectCompatibleTypes(
                    exceptionTypes, pm.exceptionTypes, legalExceptions);
                collectCompatibleTypes(
                    pm.exceptionTypes, exceptionTypes, legalExceptions);
                pm.exceptionTypes = new Class[legalExceptions.size()];
                pm.exceptionTypes =
                    legalExceptions.toArray(pm.exceptionTypes);
                return;
            }
        }
    } else {
        sigmethods = new ArrayList<ProxyMethod>(3);
        proxyMethods.put(sig, sigmethods);
    }
    sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,
                                   exceptionTypes, fromClass));
}
关于gen代理方法的完整代码
    private MethodInfo generateMethod() throws IOException {
        String desc = getMethodDescriptor(parameterTypes, returnType);
        MethodInfo minfo = new MethodInfo(methodName, desc,
            ACC_PUBLIC | ACC_FINAL);
        int[] parameterSlot = new int[parameterTypes.length];
        int nextSlot = 1;
        for (int i = 0; i < parameterSlot.length; i++) {
            parameterSlot[i] = nextSlot;
            nextSlot += getWordsPerType(parameterTypes[i]);
        }
        int localSlot0 = nextSlot;
        short pc, tryBegin = 0, tryEnd;
        DataOutputStream out = new DataOutputStream(minfo.code);
        code_aload(0, out);
        out.writeByte(opc_getfield);
        out.writeShort(cp.getFieldRef(
            superclassName,
            handlerFieldName, "Ljava/lang/reflect/InvocationHandler;"));
        code_aload(0, out);
        out.writeByte(opc_getstatic);
        out.writeShort(cp.getFieldRef(
            dotToSlash(className),
            methodFieldName, "Ljava/lang/reflect/Method;"));
        if (parameterTypes.length > 0) {
            code_ipush(parameterTypes.length, out);
            out.writeByte(opc_anewarray);
            out.writeShort(cp.getClass("java/lang/Object"));
            for (int i = 0; i < parameterTypes.length; i++) {
                out.writeByte(opc_dup);
                code_ipush(i, out);
                codeWrapArgument(parameterTypes[i], parameterSlot[i], out);
                out.writeByte(opc_aastore);
            }
        } else {
            out.writeByte(opc_aconst_null);
        }
        out.writeByte(opc_invokeinterface);
        out.writeShort(cp.getInterfaceMethodRef(
            "java/lang/reflect/InvocationHandler",
            "invoke",
            "(Ljava/lang/Object;Ljava/lang/reflect/Method;" +
                "[Ljava/lang/Object;)Ljava/lang/Object;"));
        out.writeByte(4);
        out.writeByte(0);
        if (returnType == void.class) {
            out.writeByte(opc_pop);
            out.writeByte(opc_return);
        } else {
            codeUnwrapReturnValue(returnType, out);
        }
        tryEnd = pc = (short) minfo.code.size();
        List<Class<?>> catchList = computeUniqueCatchList(exceptionTypes);
        if (catchList.size() > 0) {
            for (Class<?> ex : catchList) {
                minfo.exceptionTable.add(new ExceptionTableEntry(
                    tryBegin, tryEnd, pc,
                    cp.getClass(dotToSlash(ex.getName()))));
            }
            out.writeByte(opc_athrow);
            pc = (short) minfo.code.size();
            minfo.exceptionTable.add(new ExceptionTableEntry(
                tryBegin, tryEnd, pc, cp.getClass("java/lang/Throwable")));
            code_astore(localSlot0, out);
            out.writeByte(opc_new);
            out.writeShort(cp.getClass(
                "java/lang/reflect/UndeclaredThrowableException"));
            out.writeByte(opc_dup);
            code_aload(localSlot0, out);
            out.writeByte(opc_invokespecial);
            out.writeShort(cp.getMethodRef(
                "java/lang/reflect/UndeclaredThrowableException",
                "<init>", "(Ljava/lang/Throwable;)V"));
            out.writeByte(opc_athrow);
        }
| 归档时间: | 
 | 
| 查看次数: | 84207 次 | 
| 最近记录: |