@CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException{ // 验证传入的InvocationHandler不能为空,为空就抛出NullPointerException 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); } // 从代理类对象中查找参数为InvocationHandler的代理类构造器 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; // 检测构造器是否是Public修饰,如果不是则强行转换为可以访问的。 if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } // 传入InvocationHandler实例去构造一个代理类的实例 // 通过反射,将h作为参数,实例化代理类,返回代理类实例。 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); } }
- 1、获取代理类对象(Class<?> cl = getProxyClass0(loader, intfs))
- 2、利用反射技术实例化代理类,并返回实例化对象(return cons.newInstance(new Object[]{h}))
/** * 生成一个代理类对象, */ private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { // 接口类对象数组不能大于65535个,否则抛出异常 if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // 从代理类对象缓存中,根据类加载器和接口类对象数组查找代理类对象 return proxyClassCache.get(loader, interfaces); }
在这个方法中,是直接从一个叫proxyClassCache缓存中读取的, 如果根据提供的类加载器和接口数组能在缓存中找到代理类就直接返回该代理类。如果没有在缓存中找到,会调用ProxyClassFactory工厂去生成代理类。很明显ProxyClassFactory这个工厂就是用来生成代理类对象!
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
这里涉及到三个类:WeakCache 、KeyFactory、ProxyClassFactory,其中后面两个类都是Proxy类的静态内部类,keyFactory是用来生产key的,ProxyClassFactory是用来生产代理类对象的,这个稍后会提到。
final class WeakCache<K, P, V> { //Reference引用队列 private final ReferenceQueue<K> refQueue= new ReferenceQueue<>(); // 缓存的底层实现, key为一级缓存, value为二级缓存。 为了支持null, map的key类型设置为Object private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>(); //reverseMap记录了所有代理类生成器是否可用, 这是为了实现缓存的过期机制 private final ConcurrentMap<Supplier<V>, Boolean> reverseMap= new ConcurrentHashMap<>(); //生成二级缓存key的工厂, 这里传入的是KeyFactory private final BiFunction<K, P, ?> subKeyFactory; //生成二级缓存value的工厂, 这里传入的是ProxyClassFactory private final BiFunction<K, P, V> valueFactory; //构造方法,传入生成二级缓存key的工厂和生成二级缓存value的工厂 public WeakCache(BiFunction<K, P, ?> subKeyFactory, BiFunction<K, P, V> valueFactory) { this.subKeyFactory = Objects.requireNonNull(subKeyFactory); this.valueFactory = Objects.requireNonNull(valueFactory); } public V get(K key, P parameter) { //下面会详细介绍这个方法 } ...... }
上面的源代码中写明, WeakCache缓存的内部实现是通过ConcurrentMap来完成的,成员变量map就是二级缓存的底层实现,reverseMap是为了实现缓存的过期机制,subKeyFactory是二级缓存key的生成工厂,通过构造器传入,这里传入的值是Proxy类的KeyFactory,valueFactory是二级缓存value的生成工厂,通过构造器传入,这里传入的是Proxy类ProxyClassFactory。
// key是类加载器,parameter为接口类对象数组 public V get(K key, P parameter) { // 接口类对象数组null检查。 Objects.requireNonNull(parameter); //清除过期的缓存 expungeStaleEntries(); // 生成缓存key对象实例,如果key = null,cacheKey = new Object(); Object cacheKey = CacheKey.valueOf(key, refQueue); // 获得二级缓存 ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey); if (valuesMap == null) { //如果valuesMap为null,则新增,以CAS方式放入 //putIfAbsent方法解释:如果值存在则返回值,并且不对原来的值做任何更改,如果不存在则新增,并返回null //Absent的意思是缺席,不在 ConcurrentMap<Object, Supplier<V>> oldValuesMap= map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>()); if (oldValuesMap != null) { valuesMap = oldValuesMap; } } // 获取subKey,这里用到了上面提到的Proxy的静态内部类KeyFactory:subKeyFactory.apply(ket,parameter) // 根据代理类实现的接口数组来生成二级缓存key, 分为key0, key1, key2, keyx Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); // 通过subKey获取到二级缓存的值 Supplier<V> supplier = valuesMap.get(subKey); Factory factory = null; //这个循环提供了轮询机制, 如果条件为假就继续重试直到条件为真为止 while (true) { if (supplier != null) { // supplier might be a Factory or a CacheValue<V> instance // 4,从工厂中获取代理类对象 V value = supplier.get(); if (value != null) { // 5,返回 return value; } } //新建一个Factory实例作为subKey对应的值 if (factory == null) { //1,实例化工厂 factory = new Factory(key, parameter, subKey, valuesMap); } if (supplier == null) { //2,保存到valuesMap中 supplier = valuesMap.putIfAbsent(subKey, factory); if (supplier == null) { // successfully installed Factory // 3,赋值 supplier = factory; } // 否则, 可能期间有其他线程修改了值, 那么就不再继续给subKey赋值, 而是取出来直接用 } else { // 期间可能其他线程修改了值, 那么就将原先的值替换 if (valuesMap.replace(subKey, supplier, factory)) { // 替换成功 supplier = factory; } else { // 失败,使用原来的值 supplier = valuesMap.get(subKey); } } } }
WeakCache的get方法并没有用锁进行同步,那它是怎样实现线程安全的呢?因为它的所有会进行修改的成员变量都使用了ConcurrentMap,这个类是线程安全的。因此它将自身的线程安全委托给了ConcurrentMap, get方法尽可能的将同步代码块缩小,这样可以有效提高WeakCache的性能。我们看到ClassLoader作为了一级缓存的key,这样可以首先根据ClassLoader筛选一遍,因为不同ClassLoader加载的类是不同的。然后它用接口数组来生成二级缓存的key,这里它进行了一些优化,因为大部分类都是实现了一个或两个接口,所以二级缓存key分为key0,key1,key2,keyX。key0到key2分别表示实现了0到2个接口,keyX表示实现了3个或以上的接口,事实上大部分都只会用到key1和key2。这些key的生成工厂是在Proxy类中,通过WeakCache的构造器将key工厂传入。这里的二级缓存的值是一个Factory实例,最终代理类的值是通过Factory这个工厂来获得的。
public class Factory { //一级缓存key, 根据ClassLoader生成 private final K key; // 代理类实现的接口数组 private final P parameter; // 二级缓存key, 根据接口数组生成 private final Object subKey; //二级缓存 private final ConcurrentMap<Object, Supplier<V>> valuesMap; Factory(K key, P parameter, Object subKey, ConcurrentMap<Object, Supplier<V>> valuesMap) { this.key = key; this.parameter = parameter; this.subKey = subKey; this.valuesMap = valuesMap; } @Override public synchronized V get() { //这里再一次去二级缓存里面获取Supplier, 用来验证是否是Factory本身 Supplier<V> supplier = valuesMap.get(subKey); if (supplier != this) { //在这里验证supplier是否是Factory实例本身, 如果不则返回null让调用者继续轮询重试 //期间supplier可能替换成了CacheValue, 或者由于生成代理类失败被从二级缓存中移除了 return null; } V value = null; try { //委托valueFactory去生成代理类, 这里会通过传入的ProxyClassFactory去生成代理类 value = Objects.requireNonNull(valueFactory.apply(key, parameter)); } finally { //如果生成代理类失败, 就将这个二级缓存删除 if (value == null) { valuesMap.remove(subKey, this); } } //只有value的值不为空才能到达这里 assert value != null; // 使用弱引用包装生成的代理类 CacheValue<V> cacheValue = new CacheValue<>(value); // 将包装后的cacheValue放入二级缓存中, 这个操作必须成功, 否则就报错 if (valuesMap.replace(subKey, this, cacheValue)) { //将cacheValue成功放入二级缓存后, 再对它进行标记 reverseMap.put(cacheValue, Boolean.TRUE); } else { throw new AssertionError("Should not reach here"); } //最后返回没有被弱引用包装的代理类 return value; } }
Factory这个内部工厂类,可以看到它的get方法是使用synchronized关键字进行了同步。进行get方法后首先会去验证subKey对应的suppiler是否是工厂本身,如果不是就返回null,而WeakCache的get方法会继续进行重试。如果确实是工厂本身,那么就会委托ProxyClassFactory生成代理类,ProxyClassFactory是在构造WeakCache的时候传入的。所以这里解释了为什么最后会调用到Proxy的ProxyClassFactory这个内部工厂来生成代理类。生成代理类后使用弱引用进行包装并放入reverseMap中,最后会返回原装的代理类。
/** * 一个利用给定的类加载器和接口类数组生成,定义并返回代理类对象的工厂方法 */ private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { // 所有代理类对象的前缀 private static final String proxyClassNamePrefix = "$Proxy"; // 用原子类来生成代理类的序号,用于生成唯一代理类名称 private static final AtomicLong nextUniqueNumber = new AtomicLong(); @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); // for (Class<?> intf : interfaces) { /* *这里遍历interfaces数组进行验证, 主要做三件事情 *1.intf是否可以由指定的类加载进行加载 */ Class<?> interfaceClass = null; try { // 加载接口类,获得接口类的类对象,第二个参数为false表示不进行实例化 interfaceClass = Class.forName(intf.getName(), false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " is not visible from class loader"); } /* * 验证interfaceClass是否是一个接口. */ if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } /* * 3、interfaceClass在数组中是否有重复 */ if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } // 生成代理类的包名 String proxyPkg = null; //生成代理类的访问标志, 默认是public final的 int accessFlags = Modifier.PUBLIC | Modifier.FINAL; for (Class<?> intf : interfaces) { //获取接口的权限修饰符 int flags = intf.getModifiers(); //如果接口的访问标志不是public, 那么生成代理类的包名和接口包名相同 if (!Modifier.isPublic(flags)) { //生成的代理类的访问标志设置为final accessFlags = Modifier.FINAL; //获取接口全限定名, 例如:java.util.Collection String name = intf.getName(); int n = name.lastIndexOf('.'); //剪裁后得到包名:java.util String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxyPkg == null) { //生成的代理类的包名和接口包名一样 proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) { // 代理类如果实现不同包的接口, 并且接口都不是public的, 在这里报错 throw new IllegalArgumentException( "non-public interfaces from different packages"); } } } //如果接口访问标志都是public的话, if (proxyPkg == null) { // 生成的代理类都放到默认的包下:com.sun.proxy proxyPkg = com.sun.proxy package proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } //生成代理类的序号 long num = nextUniqueNumber.getAndIncrement(); //生成代理类的全限定名, 包名+前缀+序号, 例如:com.sun.proxy.$Proxy0 String proxyName = proxyPkg + proxyClassNamePrefix + num; //生成代理类class文件 //核心地方,用ProxyGenerator来生成字节码 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()); } } } }
在代码的 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);,生成了代理类的class文件,并且return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);返回了我们需要的代理类对象。
private static final String proxyClassNamePrefix = "$Proxy"; long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num;
所以,动态生成的代理类名称是包名+$Proxy+id序号。
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);
return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);
上述代码中可以看到,生成了代理类的class文件,并且返回了我们需要的代理类对象。那么怎么找到这个生成的代理类class文件呢。
public class ProxyGenerator { private byte[] generateClassFile() { //第一步, 将所有的方法组装成ProxyMethod对象 //首先为代理类生成toString, hashCode, equals等代理方法 addProxyMethod(hashCodeMethod, Object.class); addProxyMethod(equalsMethod, Object.class); addProxyMethod(toStringMethod, Object.class); //遍历每一个接口的每一个方法, 并且为其生成ProxyMethod对象 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 (List<ProxyMethod> sigmethods : proxyMethods.values()) { checkReturnTypes(sigmethods); } //第二步, 组装要生成的class文件的所有的字段信息和方法信息 try { //添加构造器方法 methods.add(generateConstructor()); //遍历缓存中的代理方法 for (List<ProxyMethod> sigmethods : proxyMethods.values()) { for (ProxyMethod pm : sigmethods) { //添加代理类的静态字段, 例如:private static Method m1; fields.add(new FieldInfo(pm.methodFieldName, "Ljava/lang/reflect/Method;", ACC_PRIVATE | ACC_STATIC)); //添加代理类的代理方法 methods.add(pm.generateMethod()); } } //添加代理类的静态字段初始化方法 methods.add(generateStaticInitializer()); } catch (IOException e) { throw new InternalError("unexpected I/O Exception"); } //验证方法和字段集合不能大于65535 if (methods.size() > 65535) { throw new IllegalArgumentException("method limit exceeded"); } if (fields.size() > 65535) { throw new IllegalArgumentException("field limit exceeded"); } //第三步, 写入最终的class文件 //验证常量池中存在代理类的全限定名 cp.getClass(dotToSlash(className)); //验证常量池中存在代理类父类的全限定名, 父类名为:"java/lang/reflect/Proxy" cp.getClass(superclassName); //验证常量池存在代理类接口的全限定名 for (int i = 0; i < interfaces.length; i++) { cp.getClass(dotToSlash(interfaces[i].getName())); } //接下来要开始写入文件了,设置常量池只读 cp.setReadOnly(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream dout = new DataOutputStream(bout); try { //1.写入魔数 dout.writeInt(0xCAFEBABE); //2.写入次版本号 dout.writeShort(CLASSFILE_MINOR_VERSION); //3.写入主版本号 dout.writeShort(CLASSFILE_MAJOR_VERSION); //4.写入常量池 cp.write(dout); //5.写入访问修饰符 dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER); //6.写入类索引 dout.writeShort(cp.getClass(dotToSlash(className))); //7.写入父类索引, 生成的代理类都继承自Proxy dout.writeShort(cp.getClass(superclassName)); //8.写入接口计数值 dout.writeShort(interfaces.length); //9.写入接口集合 for (int i = 0; i < interfaces.length; i++) { dout.writeShort(cp.getClass(dotToSlash(interfaces[i].getName()))); } //10.写入字段计数值 dout.writeShort(fields.size()); //11.写入字段集合 for (FieldInfo f : fields) { f.write(dout); } //12.写入方法计数值 dout.writeShort(methods.size()); //13.写入方法集合 for (MethodInfo m : methods) { m.write(dout); } //14.写入属性计数值, 代理类class文件没有属性所以为0 dout.writeShort(0); } catch (IOException e) { throw new InternalError("unexpected I/O Exception"); } //转换成二进制数组输出 return bout.toByteArray(); } }
从上面代码中看到generateClassFile()方法是按照Class文件结构进行动态拼接的。
//抽象主题 interface AbstractSubject { void request(); } //真实主题 class RealSubject implements AbstractSubject { public void request() { System.out.println("访问真实主题方法..."); } } //真实主题 class RealSubject1 implements AbstractSubject { public void request() { System.out.println("访问真实主题方法1..."); } } //动态代理类 class DynamicProxy implements InvocationHandler { private Object object; public DynamicProxy(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); Object result = method.invoke(object, args); after(); return result; } private void before() { System.out.println("hello!"); } private void after() { System.out.println("bye!"); } } //测试类 public class TestDynamicProxyPattern { public static void main(String[] args) { AbstractSubject abstractSubject = new RealSubject(); DynamicProxy dynamicProxy = new DynamicProxy(abstractSubject); Proxy.newProxyInstance(abstractSubject.getClass().getClassLoader(), abstractSubject.getClass().getInterfaces() , dynamicProxy); abstractProxy.request(); } }
下面的代码是JDK动态代理最终生成如下结构的代理类如下:
//JDK动态代理最终会为我们生成如下结构的代理类 class Proxy0 extends Proxy implements AbstractSubject { //第一步生成构造器函数 protected Proxy0(InvocationHandler h) { super(h); } //第二步, 生成静态域 private static Method m1; //hashCode方法 private static Method m2; //equals方法 private static Method m3; //toString方法 private static Method m4; //抽象接口中的request方法 //第三步, 生成代理方法(四个) @Override public int hashCode() { try { return (int) h.invoke(this, m1, null); } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } @Override public boolean equals(Object obj) { try { Object[] args = new Object[] {obj}; return (boolean) h.invoke(this, m2, args); } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } @Override public String toString() { try { return (String) h.invoke(this, m3, null); } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } @Override public void request() { try { //构造参数数组, 如果request方法有多个参数,直接向{}里面添加参数就行了 Object[] args = new Object[] {}; h.invoke(this, m4, args); } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } //第四步, 生成静态初始化方法 static { try { Class c1 = Class.forName(Object.class.getName()); Class c2 = Class.forName(AbstractSubject.class.getName()); m1 = c1.getMethod("hashCode", null); m2 = c1.getMethod("equals", new Class[]{Object.class}); m3 = c1.getMethod("toString", null); //注意参数request方法有多个参数,直接向{}里面添加参数就行了,因为request方法中没有参数,直接传一个null就行 m4 = c2.getMethod("save", new Class[]{}); //... } catch (Exception e) { e.printStackTrace(); } } } public class TestDynamicProxyPattern { public static void main(String[] args) { Object object = new RealSubject(); DynamicProxy dynamicProxy = new DynamicProxy(object); AbstractSubject abstractSubject = new Proxy0(dynamicProxy); abstractSubject.request; } }
经过层层分析,还原了动态生成的代理类的本来面: