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(); //转换成二进制数组输出
}