java基礎(chǔ)欄目今天介紹超詳細(xì)的JVM反射原理技術(shù)點(diǎn)總結(jié)哦。
反射定義
1,JAVA反射機(jī)制是在運(yùn)行狀態(tài)中
對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;
對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法和屬性;
這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為java語(yǔ)言的反射機(jī)制。
反射提供的功能:
- 在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類
- 在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象
- 在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法
- 在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法
? ??(如果屬性是private,正常情況下是不允許外界操作屬性值,這里可以用Field類的setAccessible(true)方法,暫時(shí)打開(kāi)操作的權(quán)限)
反射的使用場(chǎng)景
- Java編碼時(shí)知道類和對(duì)象的具體信息,此時(shí)直接對(duì)類和對(duì)象進(jìn)行操作即可,無(wú)需反射
- 如果編碼時(shí)不知道類或者對(duì)象的具體信息,此時(shí)應(yīng)該使用反射來(lái)實(shí)現(xiàn)
反射源碼解析
舉例API :?
Class.forName("com.my.reflectTest").newInstance()復(fù)制代碼
1. 反射獲取類實(shí)例 Class.forName("xxx");
首先調(diào)用了 java.lang.Class 的靜態(tài)方法,獲取類信息!
注意:forName()反射獲取類信息,并沒(méi)有將實(shí)現(xiàn)留給了java,而是交給了jvm去加載!
主要是先獲取 ClassLoader, 然后調(diào)用 native 方法,獲取信息,加載類則是回調(diào) 入?yún)lassLoader 進(jìn)類加載!
@CallerSensitive public static Class<?> forName(String className) throws ClassNotFoundException { // 先通過(guò)反射,獲取調(diào)用進(jìn)來(lái)的類信息,從而獲取當(dāng)前的 classLoader Class<?> caller = Reflection.getCallerClass(); // 調(diào)用native方法進(jìn)行獲取class信息 return forName0(className, true, ClassLoader.getClassLoader(caller), caller); }復(fù)制代碼
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 // 如果已經(jīng)加載了的話,就不用再加載了 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 } // 父類沒(méi)有加載到時(shí),再自己加載 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來(lái)保存鎖 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); }復(fù)制代碼
3. newInstance()
newInstance() 其實(shí)相當(dāng)于調(diào)用類的無(wú)參構(gòu)造函數(shù),主要做了三件事復(fù)制代碼
權(quán)限檢測(cè),如果不通過(guò)直接拋出異常;
查找無(wú)參構(gòu)造器,并將其緩存起來(lái);
調(diào)用具體方法的無(wú)參構(gòu)造方法,生成實(shí)例并返回;
// 首先肯定是 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() 其實(shí)相當(dāng)于調(diào)用類的無(wú)參構(gòu)造函數(shù),所以,首先要找到其無(wú)參構(gòu)造器 if (cachedConstructor == null) { if (this == Class.class) { // 不允許調(diào)用 Class 的 newInstance() 方法 throw new IllegalAccessException( "Can not call newInstance() on the Class for java.lang.Class" ); } try { // 獲取無(wú)參構(gòu)造器 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 { // 調(diào)用無(wú)參構(gòu)造器 return tmpConstructor.newInstance((Object[])null); } catch (InvocationTargetException e) { Unsafe.getUnsafe().throwException(e.getTargetException()); // Not reached return null; } }復(fù)制代碼
4. getConstructor0() 為獲取匹配的構(gòu)造方器;分三步:
1. 先獲取所有的constructors, 然后通過(guò)進(jìn)行參數(shù)類型比較; 2. 找到匹配后,通過(guò) ReflectionFactory copy一份constructor返回; 3. 否則拋出 NoSuchMethodException;
private Constructor<T> getConstructor0(Class<?>[] parameterTypes, int which) throws NoSuchMethodException { // 獲取所有構(gòu)造器 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)); }復(fù)制代碼
5. privateGetDeclaredConstructors(), 獲取所有的構(gòu)造器主要步驟;
1. 先嘗試從緩存中獲?。? 2. 如果緩存沒(méi)有,則從jvm中重新獲取,并存入緩存,緩存使用軟引用進(jìn)行保存,保證內(nèi)存可用;
// 獲取當(dāng)前類所有的構(gòu)造方法,通過(guò)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; // 調(diào)用 reflectionData(), 獲取保存的信息,使用軟引用保存,從而使內(nèi)存不夠可以回收 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獲取構(gòu)造器 res = getDeclaredConstructors0(publicOnly); } if (rd != null) { // 最后,將從jvm中讀取的內(nèi)容,存入緩存 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); } // 新創(chuàng)建緩存,保存反射信息 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更新,如果更新成功,則立即返回,否則測(cè)查當(dāng)前已被其他線程更新的情況,如果和自己想要更新的狀態(tài)一致,則也算是成功了 oldReflectionData = this.reflectionData; classRedefinedCount = this.classRedefinedCount; if (oldReflectionData != null && (rd = oldReflectionData.get()) != null && rd.redefinedCount == classRedefinedCount) { return rd; } } }復(fù)制代碼
另外,使用 relactionData() 進(jìn)行緩存保存;ReflectionData 的數(shù)據(jù)結(jié)構(gòu)如下!
// 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; } }復(fù)制代碼
6.通過(guò)上面,獲取到 Constructor 了!接下來(lái)就只需調(diào)用其相應(yīng)構(gòu)造器的 newInstance(),即返回實(shí)例了!
// 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); } // 調(diào)用native方法,進(jìn)行調(diào)用 constructor return newInstance0(c, args); }復(fù)制代碼
返回構(gòu)造器的實(shí)例后,可以根據(jù)外部進(jìn)行進(jìn)行類型轉(zhuǎn)換,從而使用接口或方法進(jìn)行調(diào)用實(shí)例功能了。
相關(guān)免費(fèi)學(xué)習(xí)推薦:java基礎(chǔ)
Atas ialah kandungan terperinci 超詳細(xì)的JVM反射原理技術(shù)點(diǎn)總結(jié)哦~. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)