3.JDK动态代理源码

201 阅读9分钟

Proxy#newProxyInstance

在看Proxy#newProxyInstance方法之前,先看下Proxy中的重要的属性和构造方法。

所有的代理类都会继承Proxy,并实现被代理类的所有接口。

    //常量:反射获取代理类的构造方法的参数列表
    private static final Class<?>[] constructorParams ={ InvocationHandler.class };

    //常量:代理类的缓存
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
	
	//代理类的InvocationHandler
    protected InvocationHandler h;
	
	//Proxy构造方法
    protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }

Proxy#newProxyInstance源码

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException{
    	//判断InvocationHandler是否为空,若为空,抛出空指针异常
        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 ={ InvocationHandler.class };
         	//获取代理类的有参构造方法的Constructor对象
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            //参数h是自定义的InvocationHandler
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            //使用自定义的InvocationHandler作为参数,调用构造函数获取代理类对象实例
            return cons.newInstance(new Object[]{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);
        }
    }

Proxy#newProxyInstance主要是生成代理类的字节码文件,然后通过反射获取代理的有参构造方法并构造1个代理类对象返回。

所以重点还是在Proxy#getProxyClass0方法中。

getProxyClass0

    private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {
        //限定代理的接口不能超过65535个
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
		//这个get方法不简单!
        // 如果代理类的缓存proxyClassCache中已经存在相应接口的代理类,直接返回
        // 否则,使用ProxyClassFactory创建代理类
        return proxyClassCache.get(loader, interfaces);
    }

WeakCache#get

WeakCache的构造方法

    //subKeyFactory 是 KeyFactory
    //valueFactory 是 ProxyClassFactory
     public WeakCache(BiFunction<K, P, ?> subKeyFactory,BiFunction<K, P, V> valueFactory) {
            this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
            this.valueFactory = Objects.requireNonNull(valueFactory);
        }
//key是classLoader parameter是interfaces,是被代理类实现的接口的集合。
public V get(K key, P parameter) {
    
    	//判断接口数组不为空
        Objects.requireNonNull(parameter);

        expungeStaleEntries();
		
    	//构建缓存key:key主要是由classloader构成
        Object cacheKey = CacheKey.valueOf(key, refQueue);

        //从map获取缓存,key是Object,value是ConcurrentMap
        //ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>();
    	//大胆猜测一下:根据classLoader作为分组,每一个classLoader对应1个ConcurrentMap
    	//每一个ConcurrentMap里面key是被代理类,value是代理类
        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
     
     	//缓存为空
        if (valuesMap == null) {
            //创建1个ConcurrentHashMap放进去,并返回旧的ConcurrentHashMap
            ConcurrentMap<Object, Supplier<V>> oldValuesMap
                = map.putIfAbsent(cacheKey,
                                  valuesMap = new ConcurrentHashMap<>());
            
            //如果oldValuesMap不为空,将oldValuesMap赋值给valuesMap why?
            //首先我们的WeakCache#get方法没加锁,往上追溯也是没加锁
            //如果没有同步措施的话,可能存在线程安全的问题。
            //假设2个线程t1,t2
            //t1首先调用valuesMap == null成立,t1暂停
            //t2执行map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>());
            //t1执行map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>());
            //那t1创建的不就覆盖了t2创建的ConcurrentHashMap
            //按照原本的设想肯定是:同1个key获取的valuesMap是1个 即同1个classLoader对应的map是1个。
            //所以下面的代码就是为了解决线程不安全的问题。
            if (oldValuesMap != null) {
                valuesMap = oldValuesMap;
            }
        }
	
		//构建subKey,好命名!
    	//言外之意:classLoader是mainKey
    	//classLoader + interface [] 是subKey呗
        Object subKey = Objects.requireNonNull
            				(subKeyFactory.apply(key, parameter));
    
    	//根据subKey获取创建代理类的工厂类
    	//看来我们猜错了存放的并不是代理类而是创建代理类的工厂类
        Supplier<V> supplier = valuesMap.get(subKey);
    
    	//class Factory implements Supplier<V>;
    	//是WeakCache的内部类
    	//Factory 实现了 Supplier 接口 
        Factory factory = null;

        while (true) {
            //步骤3:supplier不为空 调用Factory的get方法
            if (supplier != null) {
                V value = supplier.get();
                if (value != null) {
                    return value;
                }
            }
            
 			//步骤1:构造Factory
            if (factory == null) {
                factory = new Factory(key, parameter, subKey, valuesMap);
            }
            
			//步骤2:将factory放入缓存
            if (supplier == null) {
                supplier = valuesMap.putIfAbsent(subKey, factory);
                //同上为了解决线程不安全的问题
                if (supplier == null) {
                    //将factory赋值给supplier
                    supplier = factory;
                }
            } else {
                if (valuesMap.replace(subKey, supplier, factory)) {
                    supplier = factory;
                } else {
                    supplier = valuesMap.get(subKey);
                }
            }
        }
    }
Factory#构造
Factory是WeakCache的内部类
//key是classLoader 
//parameter是interfaces,是被代理类实现的接口的集合。
//subKeyFactory.apply(key, parameter)
//ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
Factory(K key, P parameter, Object subKey,ConcurrentMap<Object, Supplier<V>> valuesMap) {
            this.key = key;
            this.parameter = parameter;
            this.subKey = subKey;
            this.valuesMap = valuesMap;
        }
Factory#get
	  //该方法加了锁
       @Override
        public synchronized V get() { 
            // 重新检查一遍supplier有没有发生变化
            Supplier<V> supplier = valuesMap.get(subKey);
            if (supplier != this) {
                //返回null意味着重新进入死循环
                return null;
            }

            V value = null;
            try {
                //重点代码
                //valueFactory类型是 ProxyClassFactory
                //调用ProxyClassFactory#apply
                value = Objects.requireNonNull
                    	(valueFactory.apply(key, parameter));
            } finally {
                if (value == null) { 
                    valuesMap.remove(subKey, this);
                }
            }
            // the only path to reach here is with non-null value
            assert value != null;

            // wrap value with CacheValue (WeakReference)
            //使用WeakReference包装CacheValue
            //使用WeakReference包装CacheValue
            //使用WeakReference包装CacheValue
            //为什么使用WeakReference包装?
            //因为当一个对象仅仅被weak reference指向, 而没有任何其他strong reference指向的时候。
            //如果GC运行, 那么这个对象就会被回收。如果存在强引用同时与之关联,则进行垃圾回收时也不会回收该对象。
            //缓存固然好,但是因为缓存导致内存溢出,那就是得不偿失本末倒置了。
            CacheValue<V> cacheValue = new CacheValue<>(value);

            // put into reverseMap
            reverseMap.put(cacheValue, Boolean.TRUE);

            // try replacing us with CacheValue (this should always succeed)
            //使用cacheValue代替valuesMap中key=subKey的value
            //因为加锁了 所以必定会成功 如果没成功 肯定是哪里出问题了
            if (!valuesMap.replace(subKey, this, cacheValue)) {
                throw new AssertionError("Should not reach here");
            }

            return value;
        }
    }

ProxyClassFactory.apply

		//所有代理类的前缀:$Proxy
        private static final String proxyClassNamePrefix = "$Proxy";
 
		//生成代理类名称的计数器:类型AtomicLong
        private static final AtomicLong nextUniqueNumber = new AtomicLong(); 
	
		//apply方法 也在synchronized的范围之内
		@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);
                } 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;
			
            //非public接口,代理类的包名与接口的包名相同
            //why?
            //public是权限最大的修饰符,他可以修饰类,成员变量,成员方法,构造方法。被public修饰后,可以再任何一个类中,不管同不同包,任意使用。 
            //private可以修饰成员变量,成员方法,构造方法,不能修饰类(此刻指的是外部类,内部类不加以考虑)。
            //defalut即不写任何关键字,它可以修饰类,成员变量,成员方法,构造方法。被默认权限修饰后,其只能被本类以及同包下的其他类访问。
            //protected可以修饰成员变量,成员方法,构造方法,但不能修饰类(此处指的是外部类,内部类不加以考虑)。
            //被protected修饰后,只能被同包下的其他类访问。如果不同包下的类要访问被protected修饰的成员,这个类必须是其子类。
            //归根结底还是权限修饰符的原因:只要保证同包 就能保证代理类可以访问到接口。
            for (Class<?> intf : interfaces) {
                int flags = intf.getModifiers();
               	//
                if (!Modifier.isPublic(flags)) {
                    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) {
                // public代理接口,使用com.sun.proxy包名
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            /*
             * Choose a name for the proxy class to generate.
             * 为代理类生成名字
             */
            long num = nextUniqueNumber.getAndIncrement();
            //类名为 包名 + 类名前缀$Proxy + 自增数字
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            /*
             * Generate the specified proxy class.
             * 真正生成代理类的字节码文件的地方
             * accessFlags = Modifier.FINAL;
             * 说明生成的代理类是final
             */
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                						proxyName, interfaces, accessFlags);
            try {
                //使用类加载器将代理类的字节码文件加载到JVM中
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                throw new IllegalArgumentException(e.toString());
            }
        }
    }

回顾一下权限修饰符

同一个类同一个包不同包的子类不同包的非子类
pubulic(公共的)🐕🐕🐕🐕
protected(受保护的)🐕🐕🐕
default(默认的)🐕🐕
private(私有的)🐕

ProxyGenerator.generateProxyClass

通过前面几篇的分析,我们知道代理类是通过Proxy类的ProxyClassFactory工厂生成的。

这个工厂类会去调用ProxyGenerator类的generateProxyClass()方法来生成代理类的字节码。

ProxyGenerator这个类存放在sun.misc包下,我们可以通过OpenJDK源码来找到这个类。

该类的generateProxyClass()静态方法的核心内容就是去调用generateClassFile()实例方法来生成Class文件。

我们直接来看generateClassFile()这个方法内部做了些什么。

    public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
        ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
        final byte[] var4 = var3.generateClassFile();
        //如果saveGeneratedFiles=true 		
        //将要生成代理类的字节码文件保存在磁盘中
		//该参数对应:sun.misc.ProxyGenerator.saveGeneratedFiles
        if (saveGeneratedFiles) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    try {
                        int var1 = var0.lastIndexOf(46);
                        Path var2;
                        if (var1 > 0) {
                            Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
                            Files.createDirectories(var3);
                            var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
                        } else {
                            var2 = Paths.get(var0 + ".class");
                        }

                        Files.write(var2, var4, new OpenOption[0]);
                        return null;
                    } catch (IOException var4x) {
                        throw new InternalError("I/O exception saving generated file: " + var4x);
                    }
                }
            });
        }

        return var4;
    }

以下代码引自:www.bbsmax.com/A/amd0qVY2z…

  /**
     * 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.
         */
        //第一步, 将所有的方法组装成ProxyMethod对象
        /*
         * 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); //为代理类生成hashCode代理方法
        addProxyMethod(equalsMethod, Object.class); //为代理类生成equals代理方法
        addProxyMethod(toStringMethod, Object.class); //为代理类生成toString代理方法
        /*
         * Now record all of the methods from the proxy interfaces, giving
         * earlier interfaces precedence over later ones with duplicate
         * methods.
         */
        for (Class<?> intf : interfaces) {  //遍历每一个接口的每一个方法, 并且为其生成ProxyMethod对象
            for (Method m : intf.getMethods()) {
                addProxyMethod(m, intf);
            }
        }
        /*
         * 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.
         */ //第二步, 组装要生成的class文件的所有的字段信息和方法信息
        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", e);
        }
        if (methods.size() > 65535) {   //验证方法和字段集合不能大于65535
            throw new IllegalArgumentException("method limit exceeded");
        }
        if (fields.size() > 65535) {
            throw new IllegalArgumentException("field limit exceeded");
        }
        /* ============================================================
         * Step 3: Write the final class file.
         */
        //第三步, 写入最终的class文件
        /*
         * 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); //验证常量池中存在代理类父类的全限定名, 父类名为:"java/lang/reflect/Proxy"
        for (Class<?> intf: interfaces) {  //验证常量池存在代理类接口的全限定名
            cp.getClass(dotToSlash(intf.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); //1.写入魔数
                                        // u2 minor_version;
            dout.writeShort(CLASSFILE_MINOR_VERSION); //2.写入次版本号
                                        // u2 major_version;
            dout.writeShort(CLASSFILE_MAJOR_VERSION); //3.写入主版本号
            cp.write(dout);             // (write constant pool)  //4.写入常量池
                                        // u2 access_flags;
            dout.writeShort(accessFlags); //5.写入访问修饰符
                                        // u2 this_class;
            dout.writeShort(cp.getClass(dotToSlash(className))); //6.写入类索引
                                        // u2 super_class;
            dout.writeShort(cp.getClass(superclassName)); //7.写入父类索引, 生成的代理类都继承自Proxy
                                        // u2 interfaces_count;
            dout.writeShort(interfaces.length); //8.写入接口计数值
                                        // u2 interfaces[interfaces_count];
            for (Class<?> intf : interfaces) {
                dout.writeShort(cp.getClass( //9.写入接口集合
                    dotToSlash(intf.getName())));
            }
                                        // u2 fields_count;
            dout.writeShort(fields.size()); //10.写入字段计数值
                                        // field_info fields[fields_count];
            for (FieldInfo f : fields) {
                f.write(dout); //11.写入字段集合
            }
                                        // u2 methods_count;
            dout.writeShort(methods.size());//12.写入方法计数值
                                        // method_info methods[methods_count];
            for (MethodInfo m : methods) {
                m.write(dout); //13.写入方法集合
            }
                                         // u2 attributes_count;
            dout.writeShort(0); // (no ClassFile attributes for proxy classes) //14.写入属性计数值, 代理类class文件没有属性所以为0
        } catch (IOException e) {
            throw new InternalError("unexpected I/O Exception", e);
        }
        return bout.toByteArray(); //转换成二进制数组输出
    }