jdk源码之Constructor
一、类图
二、反射调用构造函数
两种:
- 调用无参构造函数:Class.newInstance()
- 调用带参数的构造函数:
通过 Class 类获取 Constructor
调用 Constructor 中的 newInstance(Object … initarges) 方法
其中Class.newInstance()最终调用的也是Constructor 的newInstance:
@CallerSensitive
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
}
// NOTE: the following code may not be strictly correct under
// the current Java memory model.
// Constructor lookup
if (cachedConstructor == null) {
if (this == Class.class) {
throw new IllegalAccessException(
"Can not call newInstance() on the Class for java.lang.Class"
);
}
try {
Class<?>[] empty = {};
// 可以看到这边就会获得构造函数
final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
// Disable accessibility checks on the constructor
// since we have to do the security check here anyway
// (the stack depth is wrong for the Constructor's
// security check to work)
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
c.setAccessible(true);
return null;
}
});
// 将获得的构造函数存入缓存
cachedConstructor = c;
} catch (NoSuchMethodException e) {
throw (InstantiationException)
new InstantiationException(getName()).initCause(e);
}
}
// 得到构造函数
Constructor<T> tmpConstructor = cachedConstructor;
// Security check (same as in java.lang.reflect.Constructor)
int modifiers = tmpConstructor.getModifiers();
if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
if (newInstanceCallerCache != caller) {
Reflection.ensureMemberAccess(caller, this, null, modifiers);
newInstanceCallerCache = caller;
}
}
// Run constructor
try {
// 调用构造函数的newInstance方法获得实例
return tmpConstructor.newInstance((Object[])null);
} catch (InvocationTargetException e) {
Unsafe.getUnsafe().throwException(e.getTargetException());
// Not reached
return null;
}
}
三、newInstance方法
- 根据参数创建初始化实例,参数有匹配的规则;
- 获取无参构造函数,参数长度可以为 0 或者 null;
- 有访问权限并且对参数进行检查,需要获取到构造函数的声明类;
@CallerSensitive
public T newInstance(Object ... initargs)
throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException
{
// 校验权限
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, null, modifiers);
}
}
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
// 获取构造函数的声明类
ConstructorAccessor ca = constructorAccessor; // read volatile
if (ca == null) {
// 下面有方法详解
ca = acquireConstructorAccessor();
}
//使用ConstructorAccessor创建实例
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}
acquireConstructorAccessor方法
private ConstructorAccessor acquireConstructorAccessor() {
// First check to see if one has been created yet, and take it
// if so.
ConstructorAccessor tmp = null;
// 如果root(private Constructor<T> root;)中保存了ConstructorAccessor 就直接返回
if (root != null) tmp = root.getConstructorAccessor();
if (tmp != null) {
constructorAccessor = tmp;
} else {
// 否则就让反射工厂生成一个实例,并保存到root中并返回
// 下面有方法详解
tmp = reflectionFactory.newConstructorAccessor(this);
setConstructorAccessor(tmp);
}
return tmp;
}
来到ReflectionFactory中的newConstructorAccessor方法
public ConstructorAccessor newConstructorAccessor(Constructor<?> var1) {
// 检查是否初始化
// 下面有方法详解
checkInitted();
// 获得构造方法的类的实例
Class var2 = var1.getDeclaringClass();
// 校验实例是不是抽象类,如果是抽象类就抛出异常。
if (Modifier.isAbstract(var2.getModifiers())) {
return new InstantiationExceptionConstructorAccessorImpl((String)null);
// 判断是否是 Class 实例,因为 Class 实例的构造函数是 private,所以这块也需要抛出异常。
} else if (var2 == Class.class) {
return new InstantiationExceptionConstructorAccessorImpl("Can not instantiate java.lang.Class");
// 判断这个 Class 实例是否继承 ConstructorAccessorImpl,如果是父子关系,
// 就调用 BootstrapConstructorAccessorImpl 创建 ConstructorAccessor,
// 这个方法是调用 native 方法,底层用 c++ 实现的本地接口。
} else if (Reflection.isSubclassOf(var2, ConstructorAccessorImpl.class)) {
return new BootstrapConstructorAccessorImpl(var1);
// 如果 noInflation 为 true 并且 实例不是匿名的,就是用Java 字节码存取器。
// 需要调用 MethodAccessorGenerator.generateConstructor() 创建 ConstructorAccessor,
// 原理是通过读取二进制文件,将 Class 实例加载进来,然后根据一些条件获取到想要的 Constructor。
} else if (noInflation && !ReflectUtil.isVMAnonymousClass(var1.getDeclaringClass())) {
return (new MethodAccessorGenerator()).generateConstructor(var1.getDeclaringClass(), var1.getParameterTypes(), var1.getExceptionTypes(), var1.getModifiers());
//上面的条件都不满足,就调用 NativeConstructorAccessorImpl
} else {
// 下面有方法详解
NativeConstructorAccessorImpl var3 = new NativeConstructorAccessorImpl(var1);
DelegatingConstructorAccessorImpl var4 = new DelegatingConstructorAccessorImpl(var3);
var3.setParent(var4);
return var4;
}
}
来到checkInitted方法
private static void checkInitted() {
// (initted记录是否被初始化),如果是false,就进行初始化并将initted改为true
if (!initted) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
if (System.out == null) {
return null;
} else {
// 从系统属性读取noInflation属性,默认值为false (private static boolean noInflation = false;)
// 其中系可以通过 -D= 来设置系统属性,通过 System.getProperty("属性名称") 来获取属性值。
// 如果设为true,就强制使用 Java 字节码存取器
String var1 = System.getProperty("sun.reflect.noInflation");
if (var1 != null && var1.equals("true")) {
ReflectionFactory.noInflation = true;
}
// 从系统属性读取inflationThreshold,作用是定义JNI 存取器的使用次数的阈值
// 默认值为15(private static int inflationThreshold = 15;)
// JVM 访问反射的类的信息会先从 JNI 存取器读取 15(如果不修改默认值)次之后才会使用 Java 字节码存取器
var1 = System.getProperty("sun.reflect.inflationThreshold");
if (var1 != null) {
try {
ReflectionFactory.inflationThreshold = Integer.parseInt(var1);
} catch (NumberFormatException var3) {
throw new RuntimeException("Unable to parse property sun.reflect.inflationThreshold", var3);
}
}
ReflectionFactory.initted = true;
return null;
}
}
});
}
}
JVM 有两种方法来访问有关反射的类的信息,可以使用 JNI
(JNI(Java Native Interface),通过使用 Java 本地接口书写程序,可以确保代码在不同的平台上方便移植。)
读取器或者 Java 字节码存取器。inflationThreshold 是使用 JNI 存取器的次数,值为 0 表示永不从 JNI 存取器读取。如果想强制使用 Java 字节码存取器,可以设置 noInflation 为 true。