Proxy源码解析。

/**
 * Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
 *
 * 创建某一接口 Foo 的代理:
 *
 *      InvocationHandler handler = new MyInvocationHandler(...);
 *      Class proxyClass = Proxy.getProxyClass(
 *          Foo.class.getClassLoader(), new Class[] { Foo.class });
 *      Foo f = (Foo) proxyClass.
 *          getConstructor(new Class[] { InvocationHandler.class }).
 *          newInstance(new Object[] { handler });
 *  或使用以下更简单的方法:
 *      Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
 *                                           new Class[] { Foo.class },
 *                                           handler);
 *  动态代理类(以下简称为代理类)是一个实现在创建类时在运行时指定的接口列表的类,该类具有下面描述的行为。
 *  代理接口 是代理类实现的一个接口。 代理实例 是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序 对象,
 *  它可以实现接口 InvocationHandler。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke 方法,
 *  并传递代理实例、识别调用方法的 java.lang.reflect.Method 对象以及包含参数的 Object 类型的数组。
 *  调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。
 *
 * 代理类具用以下属性:
 *
 * 代理类是公共的、最终的,而不是抽象的。
 * 未指定代理类的非限定名称。但是,以字符串 "$Proxy" 开头的类名空间应该为代理类保留。
 * 代理类扩展 java.lang.reflect.Proxy。
 * 代理类会按同一顺序准确地实现其创建时指定的接口。
 * 如果代理类实现了非公共接口,那么它将在与该接口相同的包中定义。否则,代理类的包也是未指定的。
 * 注意,包密封将不阻止代理类在运行时在特定包中的成功定义,也不会阻止相同类加载器和带有特定签名的包所定义的类。
 * 由于代理类将实现所有在其创建时指定的接口,所以对其 Class 对象调用 getInterfaces 将返回一个包含相同接口列表的数组
 * (按其创建时指定的顺序),对其 Class 对象调用 getMethods 将返回一个包括这些接口中所有方法的 Method 对象的数组,
 * 并且调用 getMethod 将会在代理接口中找到期望的一些方法。
 * 如果 Proxy.isProxyClass 方法传递代理类(由 Proxy.getProxyClass 返回的类,
 * 或由 Proxy.newProxyInstance 返回的对象的类),则该方法返回 true,否则返回 false。
 * 代理类的 java.security.ProtectionDomain 与由引导类加载器(如 java.lang.Object)加载的系统类相同,
 * 原因是代理类的代码由受信任的系统代码生成。此保护域通常被授予 java.security.AllPermission。
 * 每个代理类都有一个可以带一个参数(接口 InvocationHandler 的实现)的公共构造方法,用于设置代理实例的调用处理程序。
 * 并非必须使用反射 API 才能访问公共构造方法,通过调用 Proxy.newInstance 方法
 * (将调用 Proxy.getProxyClass 的操作和调用带有调用处理程序的构造方法结合在一起)也可以创建代理实例。
 * 代理实例具有以下属性:
 *
 * 提供代理实例 proxy 和一个由其代理类 Foo 实现的接口,以下表达式将返回 true:
 *      proxy instanceof Foo
 *  并且以下的强制转换操作将会成功(而不抛出 ClassCastException):
 *      (Foo) proxy
 *  每个代理实例都有一个关联的调用处理程序,它会被传递到其构造方法中。
 *  静态 Proxy.getInvocationHandler 方法将返回与作为其参数传递的代理实例相关的调用处理程序。
 * 代理实例上的接口方法调用将按照该方法的文档描述进行编码,并被指派到调用处理程序的 Invoke 方法。
 * 在代理实例上的 java.lang.Object 中声明的 hashCode、equals 或 toString 方法的调用
 * 将按照与编码和指派接口方法调用相同的方式进行编码,并被指派到调用处理程序的 invoke 方法,如上所述。
 * 传递到 invoke 的 Method 对象的声明类是 java.lang.Object。
 * 代理类不重写从 java.lang.Object 继承的代理实例的其他公共方法,
 * 所以这些方法的调用行为与其对 java.lang.Object 实例的操作一样。
 * 在多代理接口中重复的方法
 * 当代理类的两个或多个接口包含一个具有相同名称和参数签名的方法时,代理类的接口顺序变得非常重要。
 * 在代理实例上调用重复方法 时,传递到调用处理程序的 Method 对象没有必要成为其声明类可以从接口
 * (通过该接口调用代理方法)的引用类型指派的对象。此限制存在的原因是,生成的代理类中的相应方法
 * 实现无法确定它通过哪一个接口调用。因此,在代理实例上调用重复方法时,第一个接口中的方法的 Method 对象
 * 包含接口的代理类列表中的方法(直接或通过超级接口继承),该对象会传递到调用处理程序的 invoke 方法,
 * 无论该方法调用通过哪一种引用类型发生。
 *
 * 如果代理接口包含某一方法,它的名称和参数签名与 java.lang.Object 的 hashCode、equals 或 toString 方法相同,
 * 那么在代理实例上调用这样的方法时,传递到调用处理程序的 Method 对象将使 java.lang.Object 成为其声明类。
 * 换句话说,java.lang.Object 公共的非最终方法理论上在所有代理接口之前,以便确定哪一个 Method 对象传递到调用处理程序。
 *
 * 还要注意,当重复方法被指派到调用处理程序时,invoke 方法只可以抛出经过检查的异常类型,
 * 该异常类型可以使用所有 代理接口(可以通过它调用)中方法的 throws 子句指派一种异常类型。
 * 如果 invoke 方法抛出一个经过检查的异常,该异常没有指派给任何由一个代理接口(可以通过它调用)中的方法声明的异常类型,
 * 那么该代理实例上的调用将抛出一个未经检查的 UndeclaredThrowableException。
 * 此限制表示并非所有的由传递到 invoke 方法的 Method 对象上
 * 调用 getExceptionTypes 返回的异常类型都可以由 invoke 方法成功抛出。
 */
public class Proxy implements java.io.Serializable {

    private static final long serialVersionUID = -2222568056686623797L;

    /**
     * 代理类构造函数的参数类型
     */
    private static final Class<?>[] constructorParams = { InvocationHandler.class };

    /**
     * 代理类的缓存
     */
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
            proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

    /**
     * 此代理实例的调用处理程序。
     */
    protected InvocationHandler h;

    /**
     * 禁止实例化。
     */
    private Proxy() {
    }

    /**
     * 使用其调用处理程序的指定值从子类(通常为动态代理类)构建新的 Proxy 实例。
     * @param h 此代理实例的调用处理程序
     */
    protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }

    /**
     * 返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。
     * 该代理类将由指定的类加载器定义,并将实现提供的所有接口。如果类加载器已经定义了具有相同排列接口的代理类,
     * 那么现有的代理类将被返回;否则,类加载器将动态生成并定义这些接口的代理类。
     * 对可以传递给 Proxy.getProxyClass 的参数有以下几个限制:
     *
     * interfaces 数组中的所有 Class 对象必须表示接口,而不能表示类或基本类型。
     * interfaces 数组中的两个元素不能引用同一 Class 对象。
     * 所有接口类型的名称通过特定的类加载器必须可见。换句话说,对于类加载器 cl 和所有接口 i,以下表达式必须为 true:
     *      Class.forName(i.getName(), false, cl) == i
     *  所有非公共接口必须位于同一包中;否则,该代理类将不可能实现所有的接口,无论它在哪一个包中定义。
     * 对于有相同签名的指定接口中任何成员方法集:
     * 如果任何方法的返回类型是基本类型或 void,那么所有的方法必须具有与此相同的返回类型。
     * 否则,该方法之一必须是返回类型,它可以指派给该方法其余的所有返回类型。
     * 得到的代理类必须不超过虚拟机在类上施加的任何限制。例如,虚拟机可以限制某一类实现至多 65535 的接口数;
     * 在这种情况下,interfaces 数组的大小必须不超过 65535。
     * 如果违反了这些限制,Proxy.getProxyClass 将抛出 IllegalArgumentException。
     * 如果 interfaces 数组参数或其任何元素为 null,则将抛出 NullPointerException。
     *
     * 注意,指定的代理接口的顺序非常重要:对接口组合相同但顺序不同的代理类的两个请求会导致两个不同的代理类。
     * @param loader    定义代理类的类加载器
     * @param interfaces    代理类要实现的接口列表
     * @return  用指定的类加载器定义的代理类,它可以实现指定的接口
     * @throws IllegalArgumentException 如果违反传递到 getProxyClass 的参数上的任何限制
     */
    @CallerSensitive
    public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
            throws IllegalArgumentException
    {
        final Class<?>[] intfs = interfaces.clone(); // 创建副本
        final SecurityManager sm = System.getSecurityManager(); // 获取系统安全管理器。
        if (sm != null) {// 检查创建代理类所需的权限。
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }
        // 生成代理类
        return getProxyClass0(loader, intfs);
    }

    /**
     * 检查创建代理类所需的权限。
     *
     * 要定义代理类,它执行class.forname中的访问检查(VM将调用ClassLoader.checkPackageAccess):
     * 1. “getClassLoader”权限检查loader是否== null
     * 2. checkPackageAccess对它实现的接口的访问
     *
     * 要获取代理类的构造函数和新实例,它对实现的接口执行包访问检查,如class . getconstructor中所示。
     *
     * 如果接口是非公共的,则必须由接口的定义加载程序定义代理类。
     * 如果调用方的类加载器与接口的定义加载器不同,当通过defineClass0方法定义生成的代理类时,VM将抛出IllegalAccessError。
     * @param caller
     * @param loader    定义代理类的类加载器
     * @param interfaces    代理类要实现的接口列表
     */
    private static void checkProxyAccess(Class<?> caller,
                                         ClassLoader loader,
                                         Class<?>... interfaces)
    {
        SecurityManager sm = System.getSecurityManager();// 获取系统安全管理器。
        if (sm != null) {
            ClassLoader ccl = caller.getClassLoader(); // 获取该类的类加载器。
            // loader为空 并且ccl非空
            if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
                // 如果基于SecurityConstants.GET_CLASSLOADER_PERMISSION策略,
                // 不允许执行根据给定权限所指定的请求访问,则抛出 SecurityException。
                sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
            }
            // 检查权限
            ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
        }
    }

    /**
     * 生成代理类。在调用此方法之前,必须调用checkProxyAccess方法来执行权限检查。
     * @param loader     定义代理类的类加载器
     * @param interfaces    代理类要实现的接口列表
     * @return
     */
    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        if (interfaces.length > 65535) { // interfaces 数组的大小必须不超过 65535。
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // 如果实现给定接口的给定加载器定义的代理类存在,则只返回缓存的副本;否则,它将通过ProxyClassFactory创建代理类
        return proxyClassCache.get(loader, interfaces);
    }

    /*
     * 用于具有0个实现接口的代理类的键
     */
    private static final Object key0 = new Object();
    /*
     * Key1和Key2进行了优化,用于实现1或2个接口的动态代理的公共使用。
     */

    /**
     * 用于具有一个已实现接口的代理类的键
     */
    private static final class Key1 extends WeakReference<Class<?>> {
        private final int hash;

        Key1(Class<?> intf) {
            super(intf);
            this.hash = intf.hashCode();
        }

        /**
         *  返回该对象的哈希码值。
         * @return 此对象的一个哈希码值。
         */
        @Override
        public int hashCode() {
            return hash;
        }

        /**
         * 指示其他某个对象是否与此对象“相等”。
         * @param obj   要与之比较的引用对象。
         * @return  如果此对象与 obj 参数相同,则返回 true;否则返回 false。
         */
        @Override
        public boolean equals(Object obj) {
            Class<?> intf;
            return this == obj ||
                    obj != null &&
                            obj.getClass() == Key1.class &&
                            (intf = get()) != null &&
                            intf == ((Key1) obj).get();
        }
    }

    /**
     * 用于具有两个实现接口的代理类的键
     */
    private static final class Key2 extends WeakReference<Class<?>> {
        private final int hash;
        private final WeakReference<Class<?>> ref2;

        Key2(Class<?> intf1, Class<?> intf2) {
            super(intf1);
            hash = 31 * intf1.hashCode() + intf2.hashCode();
            ref2 = new WeakReference<Class<?>>(intf2);
        }
        /**
         *  返回该对象的哈希码值。
         * @return 此对象的一个哈希码值。
         */
        @Override
        public int hashCode() {
            return hash;
        }
        /**
         * 指示其他某个对象是否与此对象“相等”。
         * @param obj   要与之比较的引用对象。
         * @return  如果此对象与 obj 参数相同,则返回 true;否则返回 false。
         */
        @Override
        public boolean equals(Object obj) {
            Class<?> intf1, intf2;
            return this == obj ||
                    obj != null &&
                            obj.getClass() == Key2.class &&
                            (intf1 = get()) != null &&
                            intf1 == ((Key2) obj).get() &&
                            (intf2 = ref2.get()) != null &&
                            intf2 == ((Key2) obj).ref2.get();
        }
    }

    /**
     * 用于具有任意数量实现接口的代理类的键(此处仅用于3个或更多)
     */
    private static final class KeyX {
        private final int hash;
        private final WeakReference<Class<?>>[] refs;

        @SuppressWarnings("unchecked")
        KeyX(Class<?>[] interfaces) {
            hash = Arrays.hashCode(interfaces); // interfaces数组基于内容的哈希码
            refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.length];
            for (int i = 0; i < interfaces.length; i++) { // 遍历
                refs[i] = new WeakReference<>(interfaces[i]);
            }
        }

        /**
         *  返回该对象的哈希码值。
         * @return 此对象的一个哈希码值。
         */
        @Override
        public int hashCode() {
            return hash;
        }

        /**
         * 指示其他某个对象是否与此对象“相等”。
         * @param obj   要与之比较的引用对象。
         * @return  如果此对象与 obj 参数相同,则返回 true;否则返回 false。
         */
        @Override
        public boolean equals(Object obj) {
            return this == obj ||
                    obj != null &&
                            obj.getClass() == KeyX.class && equals(refs, ((KeyX) obj).refs);
        }

        /**
         * 判断两个弱引用是否相等
         * @param refs1
         * @param refs2
         * @return
         */
        private static boolean equals(WeakReference<Class<?>>[] refs1,
                                      WeakReference<Class<?>>[] refs2) {
            if (refs1.length != refs2.length) { // 长度判断
                return false;
            }
            for (int i = 0; i < refs1.length; i++) {
                Class<?> intf = refs1[i].get(); // refs1[i]所引用的对象;如果此引用对象已经清除,则返回 null。
                if (intf == null || intf != refs2[i].get()) { // 引用对象为空 或者 不一致
                    return false;
                }
            }
            return true;
        }
    }

    /**
     * 将接口数组映射到表示接口的类对象被弱引用的最优键的函数。
     */
    private static final class KeyFactory
            implements BiFunction<ClassLoader, Class<?>[], Object>
    {
        /**
         * 将此函数应用于给定的参数。
         * @param classLoader   定义代理类的类加载器
         * @param interfaces    代理类要实现的接口列表
         * @return  函数的结果
         */
        @Override
        public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
            switch (interfaces.length) { // 判断接口列表长度,返回最优键
                case 1: return new Key1(interfaces[0]); // 最常见的
                case 2: return new Key2(interfaces[0], interfaces[1]);
                case 0: return key0;
                default: return new KeyX(interfaces);
            }
        }
    }

    /**
     * 一个工厂函数,根据类加载器和接口数组生成、定义和返回代理类。
     */
    private static final class ProxyClassFactory
            implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    {
        // 所有代理类名的前缀
        private static final String proxyClassNamePrefix = "$Proxy";

        // 下一个用于生成唯一代理类名的数字
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

        /**
         * 将此函数应用于给定的参数。
         * @param loader   定义代理类的类加载器
         * @param interfaces    代理类要实现的接口列表
         * @return  函数的结果
         */
        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            for (Class<?> intf : interfaces) {
                /*
                 * 验证类装入器是否将此接口的名称解析为同一个类对象。
                 */
                Class<?> interfaceClass = null;
                try {
                    interfaceClass = Class.forName(intf.getName(), false, loader); // intf的类对象
                } catch (ClassNotFoundException e) {
                }
                if (interfaceClass != intf) {
                    throw new IllegalArgumentException(
                            intf + " is not visible from class loader");
                }
                /*
                 * 验证类对象是否实际表示接口。
                 */
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                            interfaceClass.getName() + " is not an interface");
                }
                /*
                 * 验证此接口不是重复的。
                 */
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                            "repeated interface: " + interfaceClass.getName());
                }
            }

            String proxyPkg = null;     // 包中定义代理类
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            /*
             * 记录非公共代理接口的包,以便在同一包中定义代理类。
             * 验证所有非公共代理接口都位于同一个包中。
             */
            for (Class<?> intf : interfaces) {
                int flags = intf.getModifiers(); // 获取此类修饰符。
                if (!Modifier.isPublic(flags)) { // 不是public 修饰符
                    accessFlags = Modifier.FINAL;
                    String name = intf.getName(); // 获取类名
                    int n = name.lastIndexOf('.');
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg;
                    } else if (!pkg.equals(proxyPkg)) {
                        throw new IllegalArgumentException(
                                "non-public interfaces from different packages");
                    }
                }
            }

            if (proxyPkg == null) {
                // 如果没有非公共代理接口,则使用com.sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            /*
             * 为要生成的代理类选择一个名称。
             */
            long num = nextUniqueNumber.getAndIncrement();
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            /*
             * 生成指定的代理类。
             */
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                    proxyName, interfaces, accessFlags);
            try {
                return defineClass0(loader, proxyName,
                        proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                /*
                 * 这里的ClassFormatError意味着(排除代理类生成代码中的bug)提供给
                 * 代理类创建的参数中还有其他一些无效的方面(比如超出了虚拟机限制)。
                 */
                throw new IllegalArgumentException(e.toString());
            }
        }
    }

    /**
     * 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。此方法相当于:
     *      Proxy.getProxyClass(loader, interfaces).
     *          getConstructor(new Class[] { InvocationHandler.class }).
     *          newInstance(new Object[] { handler });
     *  Proxy.newProxyInstance 抛出 IllegalArgumentException,原因与 Proxy.getProxyClass 相同。
     * @param loader    定义代理类的类加载器
     * @param interfaces    代理类要实现的接口列表
     * @param h 指派方法调用的调用处理程序
     * @return 一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口
     * @throws IllegalArgumentException  如果违反传递到 getProxyClass 的参数上的任何限制
     */
    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
            throws IllegalArgumentException
    {
        Objects.requireNonNull(h); // 检查指定的对象引用是否为空

        final Class<?>[] intfs = interfaces.clone(); // // 创建副本
        final SecurityManager sm = System.getSecurityManager();  // 获取系统安全管理器。
        if (sm != null) { // 检查创建代理类所需的权限。
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * 查找或生成指定的代理类。
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * 使用指定的调用处理程序调用其构造函数。
         */
        try {
            if (sm != null) {// 检查创建代理类所需的权限。
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
            // 与constructorParams 相匹配的公共构造方法的 Constructor 对象
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) { // 非公共代理接口
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            return cons.newInstance(new Object[]{h}); // 通过调用h的构造方法来创建的新对象
        } catch (IllegalAccessException|InstantiationException e) {
            throw new InternalError(e.toString(), e);
        } catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            if (t instanceof RuntimeException) {
                throw (RuntimeException) t;
            } else {
                throw new InternalError(t.toString(), t);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

    /**
     * 检查创建代理类所需的权限。
     * @param caller
     * @param proxyClass 生成的指定代理类
     */
    private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) {
        SecurityManager sm = System.getSecurityManager(); // 获取系统安全管理器。
        if (sm != null) {
            if (ReflectUtil.isNonPublicProxyClass(proxyClass)) { // 非公共代理类
                ClassLoader ccl = caller.getClassLoader(); // caller的类加载器。
                ClassLoader pcl = proxyClass.getClassLoader();// proxyClass的类加载器。

                // 是否检查调用者是否在代理类的不同运行时包中
                int n = proxyClass.getName().lastIndexOf('.');
                String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n);

                n = caller.getName().lastIndexOf('.');
                String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n);

                if (pcl != ccl || !pkg.equals(callerPkg)) {
                    sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
                }
            }
        }
    }

    /**
     * 当且仅当指定的类通过 getProxyClass 方法或 newProxyInstance 方法动态生成为代理类时,返回 true。
     * 此方法的可靠性对于使用它做出安全决策而言非常重要,所以此方法的实现不应仅测试相关的类是否可以扩展 Proxy。
     * @param cl    要测试的类
     * @return  如该类为代理类,则为 true,否则为 false
     */
    public static boolean isProxyClass(Class<?> cl) {
        return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
    }

    /**
     * 返回指定代理实例的调用处理程序。
     * @param proxy 返回调用处理程序的代理实例
     * @return  代理实例的调用处理程序
     * @throws IllegalArgumentException 如果参数不是一个代理实例
     */
    @CallerSensitive
    public static InvocationHandler getInvocationHandler(Object proxy)
            throws IllegalArgumentException
    {
        /*
         * 验证对象实际上是代理实例。
         */
        if (!isProxyClass(proxy.getClass())) {
            throw new IllegalArgumentException("not a proxy instance");
        }

        final Proxy p = (Proxy) proxy;
        final InvocationHandler ih = p.h;
        if (System.getSecurityManager() != null) {// 获取系统安全管理器。
            Class<?> ihClass = ih.getClass();
            Class<?> caller = Reflection.getCallerClass();
            if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(),
                    ihClass.getClassLoader()))
            {
                ReflectUtil.checkPackageAccess(ihClass);
            }
        }

        return ih;
    }

    /**
     * 生成指定代理类
     * @param loader    定义代理类的类加载器
     * @param name  代理类名
     * @param b 字节码数组
     * @param off   起始位置
     * @param len   长度
     * @return 返回指定代理类
     */
    private static native Class<?> defineClass0(ClassLoader loader, String name,
                                                byte[] b, int off, int len);
}

 

首先声明,这段源代码不是我编写的,让我们感谢这位名叫Carl Harris的大虾,是他编写了这段代码并将其散播到网上供大家学习讨论。这段代码虽然只是描述了最简单的proxy操作,但它的确是经典,它不仅清晰地描述了客户机/服务器系统的概念,而且几乎包括了Linux网络编程的方方面面,非常适合Linux网络编程的初学者学习。   这段Proxy程序的用法是这样的,我们可以使用这个proxy登录其它主机的服务端口。假如编译后生成了名为Proxy的可执行文件,那么命令及其参数的描述为:    ./Proxy   其中参数proxy_port是指由我们指定的代理服务器端口。参数remote_host是指我们希望连接的远程主机的主机名,IP地址也同样有效。这个主机名在网络上应该是唯一的,如果您不确定的话,可以在远程主机上使用uname -n命令查看一下。参数service_port是远程主机可提供的服务名,也可直接键入服务对应的端口号。这个命令的相应操作是将代理服务器的proxy_port端口绑定到remote_host的service_port端口。然后我们就可以通过代理服务器的proxy_port端口访问remote_host了。例如一台计算机,网络主机名是legends,IP地址为10.10.8.221,如果在我的计算机上执行:    [root@lee /root]#./proxy 8000 legends telnet   那么我们就可以通过下面这条命令访问legends的telnet端口。 ----------------------------------------------------------------- [root@lee /root]#telnet legends 8000 Trying 10.10.8.221... Connected to legends(10.10.8.221). Escape character is '^]' Red Hat Linux release 6.2(Zoot) Kernel 2.2.14-5.0 on an i686 Login: -----------------------------------------------------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软件求生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值