Java 反射源码学习之旅( 二 )


private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
int which) throws NoSuchMethodException
{
//1、拿到Constructor实例数组并进行筛选
Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
//2、通过对入参的比较筛选出符合条件的Constructor
【Java 反射源码学习之旅】for (Constructor<T> constructor : constructors) {
if (arrayContentsEq(parameterTypes,
constructor.getParameterTypes())) {
//3、创建副本Constructor
return getReflectionFactory().copyConstructor(constructor);
}
}
throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
}
3.2 目标类实例的构造
sun.reflect.ConstructorAccessor#newInstance
此方法主要是利用上一步创建出来的 Constructor 对象 , 进行目标类实例的构造 。Java 为了提高反射的性能 , 为类实例的构造提供了两种方案 , 一种是虚拟机自己实现的 native 方法 , 一种是 JDK 包里的 Java 方法 。
首先来看代码里对 ConstructorAccessor 对象的构造 , 通过代码可以看出在方法 newConstructorAccessor 中构造了 ConstructorAccessor 接口的两个实现类 , 两个对象进行了相互引用 , 像这样子:

Java 反射源码学习之旅

文章插图
//构造ConstructorAccessor对象
public ConstructorAccessor newConstructorAccessor(Constructor<?> var1) {
if (Modifier.isAbstract(var2.getModifiers())) {
} else {
NativeConstructorAccessorImpl var3 = new NativeConstructorAccessorImpl(var1);
DelegatingConstructorAccessorImpl var4 = new DelegatingConstructorAccessorImpl(var3);
var3.setParent(var4);
return var4;
}
}
在调用 DelegatingConstructorAccessorImpl 的 newInstance 方法时 , 相当于为 NativeConstructorAccessorImpl 做了一层代理 , 实际调用的是 NativeConstructorAccessorImpl 类实现的方法 。
public Object newInstance(Object[] var1) throws InstantiationException, IllegalArgumentException, InvocationTargetException {
return this.delegate.newInstance(var1);
}
newInstance 方法中决定使用哪种方法的是一个名为 numInvocations 的 int 类型的变量 , 每次调用到 newInstance 方法时 , 这个变量都会 + 1 , 当变量值超过阈值(15)时 , 就会使用 Java 方式进行目标类实例的创造 , 反之就会使用虚拟机实现的方式进行目标类实例的创造 。
这样做是因为 Java 版本的实现流程很长 , 其中还包含了字节码构造的流程 , 所以初次构造比较耗时 , 但是长久来说性能更好 , 而 native 版本是初期使用速度较块 , 调用频繁的话性能会有所下降 , 所以做了根据阈值来判断使用哪个版本的设计 。
public Object newInstance(Object[] var1) throws InstantiationException, IllegalArgumentException, InvocationTargetException {
if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.c.getDeclaringClass())) {
//Java方法构造对象
ConstructorAccessorImpl var2 = (ConstructorAccessorImpl)(new MethodAccessorGenerator()).generateConstructor(this.c.getDeclaringClass(), this.c.getParameterTypes(), this.c.getExceptionTypes(), this.c.getModifiers());
this.parent.setDelegate(var2);
}
//native方法实现实例化
return newInstance0(this.c, var1);
}
重点关注以下 Java 版本的实现流程 , 首先构造了一个 ConstructorAccessorImpl 类的对象 。这个对象的构造主要是依靠在代码里按照字节码文件的格式构造出来一个字节数组实现的 。首先创建了一个 ByteVactor 接口的实现类对象 , 此类有两个属性 , 一个字节数组 , 一个 int 类型的数用来标识位置 。ClassFileAssembler 类主要负责把各类值转化成字节码的格式然后填充到 ByteVactor 的实现类对象里 。最后由 ClassDefiner.defineClass 方法对字节码数组进行处理 , 构造出 ConstructorAccessorImpl 对象 。最后 ConstructorAccessorImpl 实例还是会被传给 newInstance0 () 这个 native 方法 , 以此来构造最终的目标类实例
private MagicAccessorImpl generate(final Class<?> var1, String var2, Class<?>[] var3, Class<?> var4, Class<?>[] var5, int var6, boolean var7, boolean var8, Class<?> var9) {
//创建ByteVectorImpl对象
ByteVector var10 = ByteVectorFactory.create();
//创建ClassFileAssembler对象


推荐阅读