Analysis of the reflection method
Class
Object provides the following methods for acquiring an object (Method
):
getMethod
- specific method returns the class or interface, the public can only be modified method.getDeclaredMethod
- specific method returns the class or interface.getMethods
- All public class or interface method returns, including public methods of the parent class.getDeclaredMethods
- returns the class or interface's method, including public, protected, default (package) access, and private methods, but does not include inherited methods.
Test Case
//父类
public class RefFather {
public void refFatherMethod(){
System.out.println("我是父类方法 refFatherMethod");
}
}
//子类
public class RefSon extends RefFather{
private void refSonMethod(){
System.out.println("我是子类方法 refMethod");
}
}
//测试方法
public static void main(String[] args) {
try {
//类的全限定名 即包名+类名
Class<?> clz = Class.forName("main.ref.RefSon");
Object obj = clz.newInstance();
Method refFatherMethod = clz.getMethod("refFatherMethod");
Method refSonMethod = clz.getDeclaredMethod("refSonMethod");
refSonMethod.invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
复制代码
Method
Look at the Class.getMethod(String name, Class<?>... parameterTypes)
source:
@CallerSensitive
public Method getMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
Method method = getMethod0(name, parameterTypes, true);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
}
return method;
}
复制代码
The above source we just need to focus on resolving the following questions can know
getMethod
the method exactly how to achieve.
@CallerSensitive
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
Reflection.getCallerClass()
Method method = getMethod0(name, parameterTypes, true);
@CallerSensitive
In fact, this annotation is used Java bug fixes. Preventing the user from using a double reflection to elevate privileges, whether there is a principle that should be checked only when the reflection of the depth of the caller class privilege, I had class itself is not so high authority, but I can be invoked by multiple reflections increase authority.
For chestnuts, such as the reflection of a class method requires looking up a fixed two-caller has permission (reflecting the relevant class privilege is relatively high), I can pass my own class -> reflection 1--> reflection such a call chain 2, 2 check permissions reflection reflection 1, resulting in vulnerabilities. The use of such notes, it getCallerClass
will skip has @CallerSensitive
modified the interface methods, direct look real caller ( actual caller
).
checkMemberAccess
Look at the source code of this method:
private void checkMemberAccess(int which, Class<?> caller, boolean checkProxyInterfaces) {
final SecurityManager s = System.getSecurityManager();
if (s != null) {
final ClassLoader ccl = ClassLoader.getClassLoader(caller);
final ClassLoader cl = getClassLoader0();
if (which != Member.PUBLIC) {
if (ccl != cl) {
s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
}
}
this.checkPackageAccess(ccl, checkProxyInterfaces);
}
}
复制代码
His main function is to check whether to allow clients to access members.
Default policies: Allow all clients to use plain Java Access access control.
What does that mean?
That is, if you do not take the initiative to configure SecurityManager
security manager, in accordance with the access modifier Class class to determine whether there is authority. For example, protected
allow only the same package or subclasses access, cross-package it into a private disable access.
final ClassLoader ccl = ClassLoader.getClassLoader(caller);
final ClassLoader cl = getClassLoader0();
If you have a custom SecurityManager
(calls System.setSecurityManager(new MySecurityManager())
), the caller will be to determine whether the parties with access to the same class loader, if there is, if not the public access modifier, there is no limit privileges. Under normal circumstances where the class loader ClassLoader
is the application class loader Application ClassLoader
.
Here briefly Application ClassLoader
:
This class loader is responsible for loading the user class path in the library (CLASSPATH), generally we write java classes are loaded by the class loader, the class loader is the return value getSystemClassLoader CLassLoader in () method, so it the system is called class loader. this is the default class loader in general.
Reflection.getCallerClass()
Continue to look at the source code:
/** @deprecated */
@Deprecated
public static native Class<?> getCallerClass(int var0);
复制代码
native representative of this method is actually implemented in other languages, so only illustrate the use of here.
Brief
Reflection.getCallerClass(int var0)
, we are interested can find out.If the value var0 equal to 0 or less, the process returns
class sun.reflect.Reflection
;If the value is equal to 1 var0 then return back to their class. That is what this line of code inside the class, returns the class.
If the value is equal to 2 var0, returns the caller's class is returned. For chestnuts, this method methodA A, call the methodA A in the method B, this time
Reflection.getCallerClass(int var0)
is the return of class B.
getMethod0(name, parameterTypes, true)
Continued Source OvO:
private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
MethodArray interfaceCandidates = new MethodArray(2);
Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates);
if (res != null)
return res;
// Not found on class or superclass directly
interfaceCandidates.removeLessSpecifics();
return interfaceCandidates.getFirst(); // may be null
}
private Method privateGetMethodRecursive(String name,
Class<?>[] parameterTypes,
boolean includeStaticMethods,
MethodArray allInterfaceCandidates) {
Method res;
// Search declared public methods
if ((res = searchMethods(privateGetDeclaredMethods(true),
name,
parameterTypes)) != null) {
if (includeStaticMethods || !Modifier.isStatic(res.getModifiers()))
return res;
}
// Search superclass's methods
if (!isInterface()) {
Class<? super T> c = getSuperclass();
if (c != null) {
if ((res = c.getMethod0(name, parameterTypes, true)) != null) {
return res;
}
}
}
// Search superinterfaces' methods
Class<?>[] interfaces = getInterfaces();
for (Class<?> c : interfaces)
if ((res = c.getMethod0(name, parameterTypes, false)) != null)
allInterfaceCandidates.add(res);
// Not found
return null;
}
private static Method searchMethods(Method[] methods,
String name,
Class<?>[] parameterTypes)
{
Method res = null;
String internedName = name.intern();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (m.getName() == internedName
&& arrayContentsEq(parameterTypes, m.getParameterTypes())
&& (res == null
|| res.getReturnType().isAssignableFrom(m.getReturnType())))
res = m;
}
return (res == null ? res : getReflectionFactory().copyMethod(res));
}
private Method[] privateGetDeclaredMethods(boolean publicOnly) {
checkInitted();
Method[] res;
ReflectionData<T> rd = reflectionData();
if (rd != null) {
res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
if (res != null) return res;
}
// No cached value available; request value from VM
res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
if (rd != null) {
if (publicOnly) {
rd.declaredPublicMethods = res;
} else {
rd.declaredMethods = res;
}
}
return res;
}
复制代码
When you call
getMethod0
, he called Class proprietary methodprivateGetMethodRecursive
recursively get all this class ofpublic
modified methods (containing parent).In
privateGetMethodRecursive
the current class will first of all methods to match, if there is no will to find his parent, if the parent does not will continue recursively until the top-level parent classObject
. If there is a copy of this Method is returned.
privateGetDeclaredMethods(boolean publicOnly)
Parameter is true, all public methods of this class is returned, otherwise all methods modifier.
According to privateGetDeclaredMethods
, it is not difficult to understand why getMethods () returns all public methods include the parent class, and getDeclaredFields()
get all the modifier method of the current method.
Boldly speculate about, getMethods()
should be a recursive call privateGetDeclaredMethods(true)
method, but getDeclaredMethods()
should only be called once privateGetDeclaredMethods(false)
method.
getMethods
Look at the source:
@CallerSensitive
public Method[] getMethods() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyMethods(privateGetPublicMethods());
}
private Method[] privateGetPublicMethods() {
checkInitted();
Method[] res;
ReflectionData<T> rd = reflectionData();
if (rd != null) {
res = rd.publicMethods;
if (res != null) return res;
}
//没有可用的缓存值;递归计算值。
//从获取公共声明的方法开始
MethodArray methods = new MethodArray();
{
//请注意这里
Method[] tmp = privateGetDeclaredMethods(true);
methods.addAll(tmp);
}
...
return res;
}
复制代码
getDeclaredMethods
Source as follows:
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
//请注意这里
return copyMethods(privateGetDeclaredMethods(false));
}
复制代码
Sure enough, both expected and in the same.
Finally, there is a getDeclaredMethod
method does not describe, but I believe we must read the above source code would have guessed that the implementation process.
@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
}
return method;
}
复制代码
All of the above on access to source code analysis methods have been combing Class finished ~ (@ ^ _ ^ @) ~ like it also requested a top praise, your support is the greatest force me updated.
Due to the limited technical writer, the article inevitably slightly wrong, welcome ━ ( `∀' ) Techno correct me!
Reference material
jvm comment @CallerSensitive usefulness
Everyone says low reflection efficiency of Java, where you know what the reason