In der heutigen Kolumne „Java-Grundlagen“ wird eine äußerst detaillierte Zusammenfassung der technischen Punkte des JVM-Reflexionsprinzips vorgestellt.
1. Der JAVA-Reflexionsmechanismus befindet sich imFür jedes Objekt können Sie anrufen Alle seine Methoden und Eigenschaften; Diese dynamische Informationserfassung und die Funktion des dynamischen Aufrufs von Objektmethoden werden als Reflexionsmechanismus der Java-Sprache bezeichnet.
Durch Reflektion bereitgestellte Funktionen:
Bestimmen Sie die Klasse, zu der ein Objekt zur Laufzeit gehört. Konstruieren Sie ein Objekt einer beliebigen Klasse zur Laufzeit. Bestimmen Sie die Mitgliedsvariablen und Methoden einer beliebigen Klasse zur Laufzeit.Sie kennen die spezifischen Informationen von Klassen und Objekten beim Codieren in Java. Zu diesem Zeitpunkt können Sie die Klassen und Objekte direkt ohne Reflexion bearbeiten
Wenn Sie es nicht wissen Um die spezifischen Informationen der Klasse oder des Objekts beim Codieren zu erhalten, sollten Sie Reflection verwenden, um eineClass.forName("com.my.reflectTest").newInstance()复制代码
Hinweis: Die Reflexion von forName() zum Erhalten von Klasseninformationen überlässt die Implementierung nicht Java, sondern dem JVM zum Laden! L Holen Sie sich hauptsächlich zuerst den Classloader und rufen Sie dann die native Methode auf, um Informationen zu erhalten. Die Ladeklasse soll in den ClassLoader in die Klasse geladen werden!
@CallerSensitive public static Class<?> forName(String className) throws ClassNotFoundException { // 先通过反射,获取调用进来的类信息,从而获取当前的 classLoader Class<?> caller = Reflection.getCallerClass(); // 调用native方法进行获取class信息 return forName0(className, true, ClassLoader.getClassLoader(caller), caller); }复制代码
// 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() 其实相当于调用类的无参构造函数,主要做了三件事复制代码
Berechtigungserkennung, wenn sie nicht erfolgreich ist, wird direkt eine Ausnahme ausgelöst;
Rufen Sie den Konstruktor ohne Argumente der jeweiligen Methode auf, generieren Sie eine Instanz und geben Sie sie zurück.
// 首先肯定是 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; } }复制代码
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)); }复制代码
// 获取当前类所有的构造方法,通过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; } } }复制代码
// 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; } }复制代码
// 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); }复制代码
Verwandte kostenlose Lernempfehlungen:
Java-GrundlagenDas obige ist der detaillierte Inhalt vonEine sehr detaillierte Zusammenfassung der technischen Punkte des JVM-Reflexionsprinzips ~. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!