共计 9057 个字符,预计需要花费 23 分钟才能阅读完成。
反射定义
1,JAVA 反射机制是在 运行状态中
对于任意一个类,都可能晓得这个类的所有属性和办法;
对于任意一个对象,都可能调用它的任意一个办法和属性;
这种动静获取的信息以及动静调用对象的办法的性能称为 java 语言的反射机制。
反射提供的性能:
- 在运行时判断任意一个对象所属的类
- 在运行时结构任意一个类的对象
- 在运行时判断任意一个类所具备的成员变量和办法
- 在运行时调用任意一个对象的办法
(如果属性是 private,失常状况下是不容许外界操作属性值,这里能够用 Field 类的 setAccessible(true)办法,临时关上操作的权限)
反射的应用场景
- Java 编码时晓得类和对象的具体信息,此时间接对类和对象进行操作即可,无需反射
- 如果编码时不晓得类或者对象的具体信息,此时应该应用反射来实现
反射源码解析
举例 API:
Class.forName("com.my.reflectTest").newInstance()
1. 反射获取类实例 Class.forName(“xxx”);
首先调用了 java.lang.Class 的静态方法,获取类信息!
留神:forName()反射获取类信息,并没有将实现留给了 java, 而是交给了 jvm 去加载!
次要是先获取 ClassLoader, 而后调用 native 办法,获取信息,加载类则是回调 入参 ClassLoader 进类加载!
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
// 先通过反射,获取调用进来的类信息,从而获取以后的 classLoader
Class<?> caller = Reflection.getCallerClass();
// 调用 native 办法进行获取 class 信息
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
2. java.lang.ClassLoader—–loadClass()
// java.lang.ClassLoader
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// 先获取锁
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
// 如果曾经加载了的话,就不必再加载了
Class<?> c = findLoadedClass(name);
if (c == null) {long t0 = System.nanoTime();
try {
// 双亲委托加载
if (parent != null) {c = parent.loadClass(name, false);
} else {c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
// 父类没有加载到时,再本人加载
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {resolveClass(c);
}
return c;
}
}
protected Object getClassLoadingLock(String className) {
Object lock = this;
if (parallelLockMap != null) {
// 应用 ConcurrentHashMap 来保留锁
Object newLock = new Object();
lock = parallelLockMap.putIfAbsent(className, newLock);
if (lock == null) {lock = newLock;}
}
return lock;
}
protected final Class<?> findLoadedClass(String name) {if (!checkName(name))
return null;
return findLoadedClass0(name);
}
3. newInstance()
newInstance() 其实相当于调用类的无参构造函数, 次要做了三件事
- 权限检测,如果不通过间接抛出异样;
- 查找无参结构器,并将其缓存起来;
- 调用具体方法的无参构造方法,生成实例并返回;
// 首先必定是 Class.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
// newInstance() 其实相当于调用类的无参构造函数,所以,首先要找到其无参结构器
if (cachedConstructor == null) {if (this == Class.class) {// 不容许调用 Class 的 newInstance() 办法
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 {
// 调用无参结构器
return tmpConstructor.newInstance((Object[])null);
} catch (InvocationTargetException e) {Unsafe.getUnsafe().throwException(e.getTargetException());
// Not reached
return null;
}
}
4. getConstructor0() 为获取匹配的结构方器;分三步:
1. 先获取所有的 constructors, 而后通过进行参数类型比拟;
2. 找到匹配后,通过 ReflectionFactory copy 一份 constructor 返回;
3. 否则抛出 NoSuchMethodException;
private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
int which) throws NoSuchMethodException
{
// 获取所有结构器
Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
for (Constructor<T> constructor : constructors) {
if (arrayContentsEq(parameterTypes,
constructor.getParameterTypes())) {return getReflectionFactory().copyConstructor(constructor);
}
}
throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
}
5. privateGetDeclaredConstructors(), 获取所有的结构器次要步骤;
1. 先尝试从缓存中获取;
2. 如果缓存没有,则从 jvm 中从新获取,并存入缓存,缓存应用软援用进行保留,保障内存可用;
// 获取以后类所有的构造方法,通过 jvm 或者缓存
// Returns an array of "root" constructors. These Constructor
// objects must NOT be propagated to the outside world, but must
// instead be copied via ReflectionFactory.copyConstructor.
private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) {checkInitted();
Constructor<T>[] res;
// 调用 reflectionData(), 获取保留的信息,应用软援用保留,从而使内存不够能够回收
ReflectionData<T> rd = reflectionData();
if (rd != null) {
res = publicOnly ? rd.publicConstructors : rd.declaredConstructors;
// 存在缓存,则间接返回
if (res != null) return res;
}
// No cached value available; request value from VM
if (isInterface()) {@SuppressWarnings("unchecked")
Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0];
res = temporaryRes;
} else {
// 应用 native 办法从 jvm 获取结构器
res = getDeclaredConstructors0(publicOnly);
}
if (rd != null) {
// 最初,将从 jvm 中读取的内容,存入缓存
if (publicOnly) {rd.publicConstructors = res;} else {rd.declaredConstructors = res;}
}
return res;
}
// Lazily create and cache ReflectionData
private ReflectionData<T> reflectionData() {
SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
int classRedefinedCount = this.classRedefinedCount;
ReflectionData<T> rd;
if (useCaches &&
reflectionData != null &&
(rd = reflectionData.get()) != null &&
rd.redefinedCount == classRedefinedCount) {return rd;}
// else no SoftReference or cleared SoftReference or stale ReflectionData
// -> create and replace new instance
return newReflectionData(reflectionData, classRedefinedCount);
}
// 新创建缓存,保留反射信息
private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,
int classRedefinedCount) {if (!useCaches) return null;
// 应用 cas 保障更新的线程安全性,所以反射是保障线程平安的
while (true) {ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
// try to CAS it...
if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {return rd;}
// 先应用 CAS 更新,如果更新胜利,则立刻返回,否则测查以后已被其余线程更新的状况,如果和本人想要更新的状态统一,则也算是胜利了
oldReflectionData = this.reflectionData;
classRedefinedCount = this.classRedefinedCount;
if (oldReflectionData != null &&
(rd = oldReflectionData.get()) != null &&
rd.redefinedCount == classRedefinedCount) {return rd;}
}
}
另外,应用 relactionData() 进行缓存保留;ReflectionData 的数据结构如下!
// reflection data that might get invalidated when JVM TI RedefineClasses() is called
private static class ReflectionData<T> {volatile Field[] declaredFields;
volatile Field[] publicFields;
volatile Method[] declaredMethods;
volatile Method[] publicMethods;
volatile Constructor<T>[] declaredConstructors;
volatile Constructor<T>[] publicConstructors;
// Intermediate results for getFields and getMethods
volatile Field[] declaredPublicFields;
volatile Method[] declaredPublicMethods;
volatile Class<?>[] interfaces;
// Value of classRedefinedCount when we created this ReflectionData instance
final int redefinedCount;
ReflectionData(int redefinedCount) {this.redefinedCount = redefinedCount;}
}
6. 通过下面,获取到 Constructor 了!接下来就只需调用其相应结构器的 newInstance(),即返回实例了!
// return tmpConstructor.newInstance((Object[])null);
// java.lang.reflect.Constructor
@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();
}
@SuppressWarnings("unchecked")
T inst = (T) ca.newInstance(initargs);
return inst;
}
// sun.reflect.DelegatingConstructorAccessorImpl
public Object newInstance(Object[] args)
throws InstantiationException,
IllegalArgumentException,
InvocationTargetException
{return delegate.newInstance(args);
}
// sun.reflect.NativeConstructorAccessorImpl
public Object newInstance(Object[] args)
throws InstantiationException,
IllegalArgumentException,
InvocationTargetException
{
// We can't inflate a constructor belonging to a vm-anonymous class
// because that kind of class can't be referred to by name, hence can't
// be found from the generated bytecode.
if (++numInvocations > ReflectionFactory.inflationThreshold()
&& !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {ConstructorAccessorImpl acc = (ConstructorAccessorImpl)
new MethodAccessorGenerator().
generateConstructor(c.getDeclaringClass(),
c.getParameterTypes(),
c.getExceptionTypes(),
c.getModifiers());
parent.setDelegate(acc);
}
// 调用 native 办法,进行调用 constructor
return newInstance0(c, args);
}
返回结构器的实例后,能够依据内部进行进行类型转换,从而应用接口或办法进行调用实例性能了。
总结
欢送关注公众号:前程有光,支付一线大厂 Java 面试题总结 + 各知识点学习思维导 + 一份 300 页 pdf 文档的 Java 外围知识点总结!
这些材料的内容都是面试时面试官必问的知识点,篇章包含了很多知识点,其中包含了有基础知识、Java 汇合、JVM、多线程并发、spring 原理、微服务、Netty 与 RPC、Kafka、日记、设计模式、Java 算法、数据库、Zookeeper、分布式缓存、数据结构等等。