Reflection definition
1. JAVA reflection is in running state
For any class, you can know all the attributes and methods of that class;
For any object, you can call any of its methods and properties;
This ability to dynamically retrieve information and invoke methods on objects is called the Reflection mechanism of the Java language.
Functions provided by Reflection:
- Determine the class to which any object belongs at run time
- Constructs an object of any class at run time
- Determine which member variables and methods any class has at run time
- Call a method of any object at run time
(If the property is private, the value of the property is normally not allowed to be manipulated by outsiders. You can use the setAccessible(true) method of the Field class to temporarily open the operation.)
Use scenarios for reflection
- When Java is coding, it knows the specific information about classes and objects. In this case, it can directly operate on classes and objects without reflection
- If you don’t know the class or object when coding, you should use reflection
Reflection source code parsing
For example, API:
Class.forName("com.my.reflectTest").newInstance()
Copy the code
Class. ForName (” XXX “);
First we call the static method of java.lang.Class to get the Class information!
Note: The forName() reflection takes class information and does not leave the implementation to Java, but to the JVM to load!
It is mainly to get the ClassLoader first, and then call native method to get the information, loading the class is the callback into the ClassLoader into the class loading!
@CallerSensitive public static Class<? > forName(String className) throws ClassNotFoundException {// Use reflection to obtain the Class information called in. > caller = Reflection.getCallerClass(); / / call native methods for the class information return forName0 (className, true, this getClassLoader (caller), the caller); }Copy the code
2. java.lang.ClassLoader—–loadClass()
// java.lang.ClassLoader protected Class<? > loadClass(String name, Boolean resolve) throws ClassNotFoundException {synchronized (getClassLoadingLock(name)) { Check if the class has already been loaded. > c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); Try {// Parent delegate load 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 } // If the parent class is not loaded, 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 ! 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); }Copy the code
3. newInstance()
NewInstance () actually does three things by calling the class's no-argument constructorCopy the code
-
Permission detection, if not by directly throwing an exception;
-
Find the no-parameter constructor and cache it;
-
Calls the no-argument constructor of the concrete method, generates an instance and returns it;
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 () is essentially calling the class's no-argument constructor, so, If (cachedConstructor == null) {if (this == class.class) {// Throw new does not allow calling Class newInstance() IllegalAccessException( "Can not call newInstance() on the Class for java.lang.Class" ); } try {// get the no-argument constructor 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; }} / / the Run constructor try {/ / calls a no-parameter constructor return tmpConstructor. NewInstance ((Object []) null); } catch (InvocationTargetException e) { Unsafe.getUnsafe().throwException(e.getTargetException()); // Not reached return null; }}Copy the code
4. GetConstructor0 () to get the matching constructor; In three steps:
1. Get all the constructors and then compare them by parameter type; 2. After finding a match, return a constructor from a ReflectionFactory copy. 3. Otherwise throw NoSuchMethodException;
private Constructor<T> getConstructor0(Class<? >[] parameterTypes, 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)); }Copy the code
5. PrivateGetDeclaredConstructors (), access to all the constructor main steps;
1. Try to fetch it from the cache. 2. If the cache does not have one, it obtains the file from the JVM and stores it in the cache. The cache uses soft references to save the file to ensure memory availability.
// Get all the constructors of the current class, // 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<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 {// Get a constructor from the JVM using native methods res = getDeclaredConstructors0(publicOnly); } if (rd ! 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); } // Create a new cache, Saving reflection information Private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData, int classRedefinedCount) { if (! useCaches) return null; While (true) {ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount); // try to CAS it... if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) { return rd; } // Select * from the thread where the current thread is located;} // Select * from the thread where the current thread is located; // Select * from the thread where the current thread is located; classRedefinedCount = this.classRedefinedCount; if (oldReflectionData ! = null && (rd = oldReflectionData.get()) ! = null && rd.redefinedCount == classRedefinedCount) { return rd; }}}Copy the code
In addition, use relactionData() for cache saving; The data structure of ReflectionData is as follows!
// 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;
}
}
Copy the code
6. From the above, we get Constructor! It then simply calls newInstance() of its corresponding constructor, which returns the instance!
// 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); } // Call native method constructor return newInstance0(c, args); }Copy the code
After you return an instance of the constructor, you can cast it based on the external implementation, using an interface or method to call the instance function.
conclusion
Welcome to pay attention to the public number: the future has light, receive a line of large factory Java interview questions summary + the knowledge points learning thinking guide + a 300 page PDF document Java core knowledge points summary!
These are some of the things that the interviewer should ask during the interview. These include basics, Java collections, JVMS, multi-threaded concurrency, Spring principles, microservices, Netty and RPC, Kafka, diaries, design patterns, Java algorithms, databases, Zookeeper, distributed caching, data structures, and more.