超变态传奇上线65535 超级变态65535手机传奇( 二 )



其中newInstance只是调用Constructor.newInstance来构造相应的代理类实例 , 这里重点是看getProxyClass0这个方法的实现:
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { // 代理的接口数量不能超过65535(没有这种变态吧) if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // JDK对代理进行了缓存 , 如果已经存在相应的代理类 , 则直接返回 , 否则才会通过ProxyClassFactory来创建代理 return proxyClassCache.get(loader, interfaces); }

其中代理缓存是使用WeakCache实现的 , 如下:
private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

具体的缓存逻辑这里暂不关心 , 只需要关心ProxyClassFactory是如何生成代理类的 , ProxyClassFactory是Proxy的一个静态内部类 , 实现了WeakCache的内部接口BiFunction的apply方法:
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) { // 省略验证代理接口的代码…… String proxyPkg = null; // 生成的代理类的包名 // 对于非公共接口 , 代理类的包名与接口的相同 for (Class<?> intf : interfaces) { int flags = intf.getModifiers(); if (!Modifier.isPublic(flags)) { 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) { proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } // 获取计数 long num = nextUniqueNumber.getAndIncrement(); // 默认情况下 , 代理类的完全限定名为:com.sun.proxy.$Proxy0 , com.sun.proxy.$Proxy1……依次递增 String proxyName = proxyPkg + proxyClassNamePrefix + num; // 这里才是真正的生成代理类的字节码的地方 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces); try { // 根据二进制字节码返回相应的Class实例 return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { throw new IllegalArgumentException(e.toString()); } } }

ProxyGenerator是sun.misc包中的类 , 它没有开源 , 但是可以反编译来一探究竟:
public static byte[] generateProxyClass(final String var0, Class[] var1) { ProxyGenerator var2 = new ProxyGenerator(var0, var1); final byte[] var3 = var2.generateClassFile(); // 这里根据参数配置 , 决定是否把生成的字节码(.class文件)保存到本地磁盘 , 我们可以通过把相应的class文件保存到本地 , 再反编译来看看具体的实现 , 这样更直观 if(saveGeneratedFiles) { AccessController.doPrivileged(new PrivilegedAction() { public Void run() { try { FileOutputStream var1 = new FileOutputStream(ProxyGenerator.dotToSlash(var0) + ".class"); var1.write(var3); var1.close(); return null; } catch (IOException var2) { throw new InternalError("I/O exception saving generated file: " + var2); } } }); } return var3; }

saveGeneratedFiles这个属性的值从哪里来呢:
private static final boolean saveGeneratedFiles = ((Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"))).booleanValue();


特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。