Method的invoke方法初步了解

Java调试过程中,我们有时候会需要对JVM运行过程中哪出了问题进行调试,先从最基础的了解。

 

我们都知道Java框架中方法的调用基本上都是通过反射机制来实施的,具体流程如下:

 

1、方法的调用先检查AccessibleObject的override属性是否是true,如果是则表明该方法是复写的方法,可以忽略访问权限的限制,直接访问。如果不是则进行访问权限检测,用sun.reflect.Reflection的quickCheckMemberAccess方法先检验是不是public,如果不是则再用sun.reflect.Reflection.getCallerClass()方法获得调用这个方法的Class,然后再做是否有权限访问的校验,检验之后会将结果缓存

 

2、sun.reflect.ReflectionFactory调用方法newMethodAccessor创建方法访问器时,私有静态变量noInflation如果为true则直接返回MethodAccessorGenerator创建的一个MethodAccessor,否则返回DelegatingMethodAccessorImpl类,并将DelegatingMethodAccessorImpl与一个NativeMethodAccessorImpl互相引用。但DelegatingMethodAccessorImpl执行invoke方法的时候又委托给NativeMethodAccessorImpl。

 

3、NativeMethodAccessorImpl的invkoe方法,NativeMethodAccessorImpl类中有一个计数器numInvocations,每调用一次方法自增加1一次,当比 ReflectionFactory的静态常量inflationThreshold(15)大的时候,用MethodAccessorGenerator创建一个MethodAccessor,并把之前的DelegatingMethodAccessorImpl引用替换为现在新创建的MethodAccessorImpl(MethodAccessorGenerator创建的MethodAccessor强制类型转换为MethodAccessorImpl),其中MethodAccessorGenerator使用了asm(assembly)字节码动态加载技术,汇编命令有更高的执行效率。

4、Method类中的invoke方法拿到的MethodAccessor对象是被volatile变量。

总结:一个方法可以生成多个Method对象,但只有一个root对象,主要用于持有一个MethodAccessor对象,这个对象也可以认为一个方法只有一个,相当于是static的。因为Method的invoke是交给MethodAccessor执行的

我们在对加了@Test注解的方法进行debug时,JUnitCore类定义了一系列方法来启动JUnit完成对测试类的反射执行,InvokeMethod类的evaluate方法会使用测试方法(FrameworkMethod类)的invokeExplosively调用该方法的返回结果。

 

备注:

1、

访问权限 当前类 同一包 子类 其他包
public
protect ×
friendly(默认) × ×
private × × ×

        

2、源码中很多方法用native修饰符,这种修饰符表明方法是该方法的实现由非java语言实现(A native method is a Java method whose implementation is provided by non-java code.)。当被native修饰时,描述符块会有一个指向该实现方法的指针。

 

3、参考:https://www.cnblogs.com/onlywujun/p/3519037.html,文中的Reflection.getCallerClass(1)方法在JDK8 版本已过时(加上@Deprecated注解),使用静态本地方法getCallerClass()加上@CallerSensitive解决通过双重反射提升权限的漏洞

你可能感兴趣的:(基础)