JDK动态代理源码阅读

JDK动态代理源码阅读(代理类生成与缓存分析)

JDK动态代理的关键:

  • 代理类字节码生成
  • 将代理类字节码加载到虚拟机中
Proxy类中的newProxyInstance方法:
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);
        }

        /*
         * Look up or generate the designated proxy class.
         *寻找或生成指定的代理类
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         *用指定的Invacation handler调用它的构造函数
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
            //获得代理类的构造函数
            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});
        } 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类中的getProxyClass0方法:
private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        //检查被代理类的接口数量是否大于65535                                   
        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;
        //如果给定的接口数组存在,将从缓存中返回代理类的Class对象
        // otherwise, it will create the proxy class via the ProxyClassFactory
        //否则,将通过ProxyClassFactory产生代理类的Class对象
        return proxyClassCache.get(loader, interfaces);
    }
WeakCache类中的get方法:
WeakCache继承了WeakReference即弱引用
原因:使用cache时,由于cache对象正式程序运行所需要的,那么只要程序,cache中的引用就不会被GC
回收(cache中的引用拥有和主程序一样的生命周期),对着引用越来越多,但GC却无法回收,导致内存溢出
解决:cache中使用弱引用。弱引用的特点,当一个对象被弱引用指向时,如果GC运行,就会将该对象回收
使用弱引用:
Object obj = new Object();
WeakReference<Object> weakObj = new WeakReference(Object)(obj);
判断弱引用是否被回收:
weakObj.get();


public V get(K key, P parameter) {
        //接口数组是否为空
        Objects.requireNonNull(parameter);
        //删除旧的条目
        expungeStaleEntries();
        //当key为null时,返回一个Object代替null,否则返回new CacheKey<>(key, refQueue)
        Object cacheKey = CacheKey.valueOf(key, refQueue);

        // lazily install the 2nd level valuesMap for the particular cacheKey
        //延迟加载二级缓存对于指定的cacheKey
        //支持null键的map private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>>
        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
        if (valuesMap == null) {
        //putIfAbsent方法,如果map中存在该key,则返回返回该key对应的对象,不存在则将该对象加入到map中
            ConcurrentMap<Object, Supplier<V>> oldValuesMap
                = map.putIfAbsent(cacheKey,
                                  valuesMap = new ConcurrentHashMap<>());
            if (oldValuesMap != null) {
                valuesMap = oldValuesMap;
            }
        }

        // create subKey and retrieve the possible Supplier<V> stored by that
        // subKey from valuesMap
        //创建一个subKey,并从keyFactory中检索subKey,此时的apply是keyFactory中的apply方法
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
        //通过subKey获得Supplier<V>
        Supplier<V> supplier = valuesMap.get(subKey);
        Factory factory = null;

        while (true) {
            if (supplier != null) {
                // supplier might be a Factory or a CacheValue<V> instance
                //supplier可以是一个工程或是CacheValue<V>的实例
                V value = supplier.get();//WeakCache.Factory.get()
                if (value != null) {
                    return value;
                }
            }
            // else no supplier in cache
            //cache中没有supplier
            // or a supplier that returned null (could be a cleared CacheValue
            // or a Factory that wasn't successful in installing the CacheValue)
            //返回的supplier为null(可能是一个清空了的CacheValue,或是一个没有被成功装入在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 {
                //不为空将valuesMap中的节点替换
                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);
                }
            }
        }
    }
WeakCache.Factory.get()
@Override
        public synchronized V get() { // serialize access序列化访问
            // re-check
            Supplier<V> 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<V> cacheValue = new CacheValue<>(value);

            // try replacing us with CacheValue (this should always succeed)
            if (valuesMap.replace(subKey, this, cacheValue)) {
                // put also in reverseMap
                //将cacheValue成功放入二级缓存后, 再对它进行标记
                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;
        }
    }
ProxyClassFactory.apply()
    @Override
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

        Map<Class<?>, 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对象是否为一个接口
             */
            if (!interfaceClass.isInterface()) {
                throw new IllegalArgumentException(
                    interfaceClass.getName() + " is not an interface");
            }
            /*
             * Verify that this interface is not a duplicate.
             *验证此接口是不是一个副本
             */
             //如果没有键映射则返回null
            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; //或运算访问修饰符 accssFlags 00000011

        /*
         * 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");
                }
            }
        }

        if (proxyPkg == null) {
            // if no non-public proxy interfaces, use com.sun.proxy package
            //如果没有非公共代理接口,请使用com.sun.proxy 包
            proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
        }

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

        /*
         * Generate the specified proxy class.
         *生成指定的代理类
         */
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
            proxyName, interfaces, accessFlags);
        try {
            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());
        }
    }
ProxyGenerator.generateProxyClass()
public class ProxyGenerator_generateClassFile {
	private byte[] generateClassFile() {
		  /* ============================================================
		   * Step 1: Assemble ProxyMethod objects for all methods to generate proxy dispatching code for.
		   * 步骤1:为所有方法生成代理调度代码,将代理方法对象集合起来。
		   */
		  //增加 hashcode、equals、toString方法
		  addProxyMethod(hashCodeMethod, Object.class);
		  addProxyMethod(equalsMethod, Object.class);
		  addProxyMethod(toStringMethod, Object.class);
		  //增加接口方法
		  for (Class<?> intf : interfaces) {
		   for (Method m : intf.getMethods()) {
		    addProxyMethod(m, intf);
		   }
		  }
		 
		  /*
		   * 验证方法签名相同的一组方法,返回值类型是否相同;意思就是重写方法要方法签名和返回值一样
		   */
		  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", e);
		  }
		 
		  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.
		   * 步骤3:编写最终类文件
		   */
		  /*
		   * 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 (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 {
		   // u4 Class文件魔数;
		   dout.writeInt(0xCAFEBABE);
		   // u2 次要版本;
		   dout.writeShort(CLASSFILE_MINOR_VERSION);
		   // u2 主版本
		   dout.writeShort(CLASSFILE_MAJOR_VERSION);
		 
		   cp.write(dout);    // (write constant pool)
		 
		   // u2 访问标识;
		   dout.writeShort(accessFlags);
		   // u2 本类名;
		   dout.writeShort(cp.getClass(dotToSlash(className)));
		   // u2 父类名;
		   dout.writeShort(cp.getClass(superclassName));
		   // u2 接口;
		   dout.writeShort(interfaces.length);
		   // u2 interfaces[interfaces_count];
		   for (Class<?> intf : interfaces) {
		    dout.writeShort(cp.getClass(
		      dotToSlash(intf.getName())));
		   }
		   // u2 字段;
		   dout.writeShort(fields.size());
		   // field_info fields[fields_count];
		   for (FieldInfo f : fields) {
		    f.write(dout);
		   }
		   // u2 方法;
		   dout.writeShort(methods.size());
		   // method_info methods[methods_count];
		   for (MethodInfo m : methods) {
		    m.write(dout);
		   }
		   // u2 类文件属性:对于代理类来说没有类文件属性;
		   dout.writeShort(0); // (no ClassFile attributes for proxy classes)
		 
		  } catch (IOException e) {
		   throw new InternalError("unexpected I/O Exception", e);
		  }
		 
		  return bout.toByteArray();
		 }

}

JDK动态代理在生成代理类是时,会先在proxyClassCache的缓存中寻找是否存在该代理类,如果存在就返回,没有就会生成相应的代理类

缓存结构:

ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = 
new ConcurrentHashMap<>()
key为一级缓存,value为二级缓存
key 的为cacheKey,类型CacheKey
二级缓存key为subkey,value为Supplier,里面存储了Class对象

二级缓存key的subKey,类型为object且支持null(使用Object代替null)
二级缓存key工厂:
private final BiFunction<K, P, ?> subKeyFactory;
二级缓存value工厂:
private final BiFunction<K, P, V> valueFactory;

Object cacheKey = CacheKey.valueOf(key, refQueue);

----------------------------------------------------------------------------
根据类加载器可引用对列返回cacheKey
static <K> Object valueOf(K key, ReferenceQueue<K> refQueue) {
            return key == null
                   // null key means we can't weakly reference it,
                   // so we use a NULL_KEY singleton as cache key
                   ? NULL_KEY
                   // non-null key requires wrapping with a WeakReference
                   : new CacheKey<>(key, refQueue);
        }

----------------------------------------------------------------------------
private CacheKey(K key, ReferenceQueue<K> refQueue) {
            super(key, refQueue);
            this.hash = System.identityHashCode(key);  // compare by identity
        }
----------------------------------------------------------------------------
调用subKeyFactory生成subKey:
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
----------------------------------------------------------------------------
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);
            }
        }
根据类加载器和接口数组返回subKey
case 1 : 一个接口
case 2 : 2个接口
case 0 : 0个接口
default 多个接口
----------------------------------------------------------------------------
Key1类:
private static final class Key1 extends WeakReference<Class<?>> {
        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) {
            Class<?> intf;
            return this == obj ||
                   obj != null &&
                   obj.getClass() == Key1.class &&
                   (intf = get()) != null &&
                   intf == ((Key1) obj).get();
        }
    }
    Key2,KeyX。。。。
----------------------------------------------------------------------------


从缓存查找代理类的流程:

首先会根据类加载器和引用队列(貌似并没有什么作用),生成一级缓存的cacheKey,根据cacheKey获取相应的二级缓存valueMap,如果二级缓存为空,就将创建一个一级缓存对象oldValuesMap,key为当前的cacheKey,value为ConcurrentHashMap,并将该对象放入一级缓存map中,再将oldValuesMap赋值给valueMap,接下来根据类加载器和接口数组获得subKey,再根据subkey从二级换从中寻找相应的代理类,如果有则返回,没有则创建该代理类

二级缓存的作用:

一级缓存中的对象以类加载器划分,二级缓存中的对象以接口数量划分。根据不同划分标准,将缓存划分为一个树形结构存储Class对象,但是map的时间复杂度为O(1),这样做的目的?有知道的大佬麻烦请告诉我,谢谢
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值