jdk动态代理源码(二)

本篇文章说的动态代理均指JDK动态代理
假如面试时有人问你:
1、为什么只有实现接口的类才能用jdk动态代理增强?
2、假设两个不同第三方jar包的类a和b都实现了同一个接口,现在对a和b使用jdk代理增强会生成几个代理类的Class对象?为什么?
3、接上一个问题,如果使用jdk动态代理时a和b分别指定了不同的类加载器,会生成几个代理类的Class对象?为什么?
4、应用运行期间会产生大量的代理类Class对象,如果太多会不会导致内存不足?什么情况下会回收这些对象?
5、如果使用jdk动态代理时a和b都没有指定类加载器,会怎样?
6、卸载类加载器时其对应的代理类Class对象是否会被释放回收?
怎么样小伙伴是不是已经满头大汗了,不要着急让我来跟你一一分析,看完源码所有问题就水落石出了。
看之前建议大家先看一下相关文章
代理模式
JDK动态代理源码(一)
jdk动态代理的入口方法:newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
下面的代码为了让大家看得更清晰,去掉了一些暂时不需要关心的东西

public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)  throws IllegalArgumentException
    {
         //InvocationHandler和接口的Class不能为空
        Objects.requireNonNull(h);
        final Class[] intfs = interfaces.clone();
       
        /*
         *获取代理类的Class对象
         */
        Class cl = getProxyClass0(loader, intfs);

        /*
        *  生成指定Handler的构造对象
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            final Constructor cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            }
            //构建代理对象的实例
            return cons.newInstance(new Object[]{h});
        } catch (Exception e) {
           //省略
        } 
    }

这个跟我们之前写的JDK动态代理源码(一)是一样的。动态生成代理类的源码,编译,加载到内存,反射获取对象的构造方法并构建实例。忘记的小伙伴可以再回头看一下。
我们来重点看一下获取代理类的Class对象这个方法

    private static Class getProxyClass0(ClassLoader loader, Class... interfaces) {
        //集成接口数量限制
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
        // If the proxy class defined by the given loader implementing;-------------如果代理类被指定的类加载器实现
        // the given interfaces exists, this will simply return the cached copy;-----并且给定的接口存在(存在于缓存map中)将仅返回缓存的对象
        // otherwise, it will create the proxy class via the ProxyClassFactory;-----否则,将通过代理类工厂返回代理类
        return proxyClassCache.get(loader, interfaces);
    }

到这里我们就需要看一下代码中proxyClassCache指的是什么,还有注释中ProxyClassFactory指的是什么。顺便把Proxy类中其他的东西都看一下。
jdk动态代理源码(二)_第1张图片
Key1、Key2、KeyX是内部类,都继承自WeakRefrence,也就是本质都是虚引用,重写了hashCode和equals,这是为了构建接口Class对象的虚引用,同时又作为后面要讲到的缓存map的key的。Key1、Key2、KeyX分别相应实现了一个接口、两个接口、多个接口的类的代理key;
因为一般多数被代理类都是实现了一个接口或者两个接口的这样设计是为了性能考虑,不必为了实现一个接口的类初始化定义数组,这个思路也值得大家借鉴
jdk动态代理源码(二)_第2张图片

    private static final class Key1 extends WeakReference> {
        private final int hash;

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

        @Override
        public int hashCode() {
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            //省略
        }
    }

KeyFactory内部类是用来生成缓存key的,这是一个实现了函数式接口BiFunction的类,有关函数式编程大家可以看《java8实战》这本书讲的还可以。

private static final class KeyFactory
        implements BiFunction[], Object>
    {
        @Override
        public Object apply(ClassLoader classLoader, Class[] interfaces) {
            switch (interfaces.length) {
                case 1: return new Key1(interfaces[0]); // the most frequent
                case 2: return new Key2(interfaces[0], interfaces[1]);
                case 0: return key0;
                default: return new KeyX(interfaces);
            }
        }
    }

ProxyClassFactory用来生成代理类的,也是一个实现了函数式接口BiFunction的类

    private static final class ProxyClassFactory
        implements BiFunction[], Class>
    {
        // prefix for all proxy class names------代理类名字前缀
        private static final String proxyClassNamePrefix = "$Proxy";

        // next number to use for generation of unique proxy class names------递增生成代理类名字,会拼接上面的$Proxy比如第一个代理类$Proxy0,第二个$Proxy1.。。
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

        @Override
        public Class apply(ClassLoader loader, Class[] interfaces) {
			//用来接口排重
            Map, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            for (Class intf : interfaces) {
                /*
                 * Verify that the class loader resolves the name of this
                 * interface to the same Class object.------该Class是否对指定的加载器可见
                 */
                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");
                }
                /*
                 * Verify that the Class object actually represents an
                 * interface.----------校验只能是接口的Class对象,所以jdk动态代理只能基于接口
                 */
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
                }
                /*
                 * Verify that this interface is not a duplicate.------排重
                 */
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
                }
            }

            String proxyPkg = null;     // package to define proxy class in
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            /*
             * Record the package of a non-public proxy interface so that the
             * proxy class will be defined in the same package.  Verify that
             * all non-public proxy interfaces are in the same package.--------包内可见的接口将代理类生成路径指定到包内
             */
            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");
                    }
                }
            }
			//代理类默认路径com.sun.proxy
            if (proxyPkg == null) {
                // if no non-public proxy interfaces, use com.sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            /*
             * Choose a name for the proxy class to generate.----------生成代理类名$Proxy0...
             */
            long num = nextUniqueNumber.getAndIncrement();
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            /*
             * Generate the specified proxy class.----------此处调用native方法生成代理类文件
             */
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
              //也是native方法加载到内存并返回Class代理类对象
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                /*
                 * A ClassFormatError here means that (barring bugs in the
                 * proxy class generation code) there was some other
                 * invalid aspect of the arguments supplied to the proxy
                 * class creation (such as virtual machine limitations
                 * exceeded).
                 */
                throw new IllegalArgumentException(e.toString());
            }
        }
    }

剩下的proxyClassCache 定义如下

    /**
     * a cache of proxy classes
     */
    private static final WeakCache[], Class>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

WeakCache类:可以理解为一个Map>结构的缓存类,
一个按照类加载器,接口,代理类排列的二级缓存map。

final class WeakCache {

    private final ReferenceQueue refQueue
        = new ReferenceQueue<>();
    // the key type is Object for supporting null key
    private final ConcurrentMap>> map
        = new ConcurrentHashMap<>();
    private final ConcurrentMap, Boolean> reverseMap
        = new ConcurrentHashMap<>();
    private final BiFunction subKeyFactory;
    private final BiFunction valueFactory;

前面的入口方法我们看到了这里:return proxyClassCache.get(loader, interfaces);
其中 proxyClassCache是一个WeakCache实例,调用了它的get方法,参数为classLoder和interfaces

 public V get(K key, P parameter) {
        Objects.requireNonNull(parameter);

        expungeStaleEntries();
		//一级map的key,是classLoder的虚引用,看一下valueOf方法如果loder为空则返回一个private static final Object NULL_KEY = new Object();
		//不指定loder时一级map的key为NULL_KEY 
        Object cacheKey = CacheKey.valueOf(key, refQueue);

        // lazily install the 2nd level valuesMap for the particular cacheKey----获取二级缓存map如果没有就初始化一个
        ConcurrentMap> valuesMap = map.get(cacheKey);
        if (valuesMap == null) {
            ConcurrentMap> oldValuesMap
                = map.putIfAbsent(cacheKey,
                                  valuesMap = new ConcurrentHashMap<>());
            if (oldValuesMap != null) {
                valuesMap = oldValuesMap;
            }
        }

        // create subKey and retrieve the possible Supplier stored by that
        // subKey from valuesMap
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
        //获取二级缓存的value,Factory对象
        Supplier supplier = valuesMap.get(subKey);
        Factory factory = null;

        while (true) {
            if (supplier != null) {
            //suplier可能是缓存也可能是Factory对象-----缓存其实也是Factory对象
                // supplier might be a Factory or a CacheValue instance
                //suplier也是函数式接口
                V value = supplier.get();              //这里获取代理类Class对象,调用的是Factory对象的get()
                if (value != null) {
                    return value;
                }
            }
            // else no supplier in cache
            // or a supplier that returned null (could be a cleared CacheValue
            // or a Factory that wasn't successful in installing the CacheValue)

            // lazily construct a Factory
            if (factory == null) {
                factory = new Factory(key, parameter, subKey, valuesMap);
            }

            if (supplier == null) {
                supplier = valuesMap.putIfAbsent(subKey, factory);
                if (supplier == null) {
                    // successfully installed Factory
                    supplier = factory;
                }
                // else retry with winning supplier
            } else {
                if (valuesMap.replace(subKey, supplier, factory)) {
                    // successfully replaced
                    // cleared CacheEntry / unsuccessful Factory
                    // with our Factory
                    supplier = factory;
                } else {
                    // retry with current supplier
                    supplier = valuesMap.get(subKey);
                }
            }
        }
    }

Factory也是函数式接口,get()方法为传递的行为
重点是 value = Objects.requireNonNull(valueFactory.apply(key, parameter));这句才是真正实现获取代理类Class对象的方法
属性valueFactory:是构造WeakCache类时传入的第二个构造参数。
jdk动态代理源码(二)_第3张图片

private final class Factory implements Supplier {

        private final K key;
        private final P parameter;
        private final Object subKey;
        private final ConcurrentMap> valuesMap;

        Factory(K key, P parameter, Object subKey,
                ConcurrentMap> valuesMap) {
            this.key = key;
            this.parameter = parameter;
            this.subKey = subKey;
            this.valuesMap = valuesMap;
        }

        @Override
        public synchronized V get() { // serialize access
            // re-check
            Supplier supplier = valuesMap.get(subKey);
            if (supplier != this) {
                // something changed while we were waiting:
                // might be that we were replaced by a CacheValue
                // or were removed because of failure ->
                // return null to signal WeakCache.get() to retry
                // the loop
                return null;
            }
            // else still us (supplier == this)

            // create new value
            V value = null;
            try {
                value = Objects.requireNonNull(valueFactory.apply(key, parameter));
            } finally {
                if (value == null) { // remove us on failure
                    valuesMap.remove(subKey, this);
                }
            }
            // the only path to reach here is with non-null value
            assert value != null;

            // wrap value with CacheValue (WeakReference)
            CacheValue cacheValue = new CacheValue<>(value);

            // try replacing us with CacheValue (this should always succeed)
            if (valuesMap.replace(subKey, this, cacheValue)) {
                // put also in reverseMap
                reverseMap.put(cacheValue, Boolean.TRUE);
            } else {
                throw new AssertionError("Should not reach here");
            }

            // successfully replaced us with new CacheValue -> return the value
            // wrapped by it
            return value;
        }
    }

再回头看一下Proxy的代码

    private static final WeakCache[], Class>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

因此value = Objects.requireNonNull(valueFactory.apply(key, parameter));调用的是Proxy.ProxyClassFactory.apply方法,这个方法我们上文分析过了。
到这里大家应该弄懂jdk动态代理的原理和实现了吧,再也不怕面试问jdk动态代理的相关问题了。

你可能感兴趣的:(源码系列)