详解Java中方法的调用方法

  

在写代码的时候,发现从父类类通过getDeclaredMethod获取的方法可以调用子类的对象,而子类改写了这个方法,从子类类通过getDeclaredMethod也能获取到方法,这时去调用父类的对象也会报错。虽然这是很符合多态的现象,也符合java的动态绑定规范,但还是想弄懂java是如何实现的,就学习了下方法的源代码只
  方法的调用方法,
  

  

<强> 1。先检查,AccessibleObject的覆盖属性是否为真的。

  

AccessibleObject是方法、字段构造函数的父类,覆盖属性默认为假,可调用种setAccessible方法改变,如果设置为真,则表示可以忽略访问权限的限制,直接调用。
  

  

2。如果不是真正的,则要进行访问权限检测。用反射的quickCheckMemberAccess方法先检查是不是公共的,如果不是再用Reflection.getCallerClass(1)方法获

  

得到调用这个方法的类,然后做是否有权限访问的校验,校验之后缓存一次,以便下次如果还是这个类来调用就不用去做校验了,直接用上次的结果,(很奇怪用这种方式缓存,因为这种方式如果下次换个类来调用的话,就不用会缓存了,而再验证一遍,把这次的结果做为缓存,但上一次的缓存结果就被冲掉了。这是一个很简单的缓冲机制,只适用于一个类的重复调用)只
  

  

3。调用MethodAccessor的调用方法。每个方法对象包含一个根对象,根对象里持有一个MethodAccessor对象。我们获得的方法独享相当于一个根对象的镜像,所有这类方法共享根里的MethodAccessor对象,(这个对象由ReflectionFactory方法生成,ReflectionFactory对象在类的方法中是static 最后的由本地方法实例化)。
  

  

ReflectionFactory生成MethodAccessor:如果noInflation的属性为真则直接返回MethodAccessorGenerator创建的一个MethodAccessor。否则返回DelegatingMethodAccessorImpl,并将他与一个NativeMethodAccessorImpl互相引用。但DelegatingMethodAccessorImpl执行调用方法的时候又委托给NativeMethodAccessorImpl了。
  

  

再一步深入

  

4. nativemethodaccessorimpl的invkoe方法:

  

调用natiave方法invoke0执行方法调用。

  

注意这里有一个计数器numInvocations,每调用一次方法+ 1,当比,ReflectionFactory.inflationThreshold(15)大的时候,用MethodAccessorGenerator创建一个MethodAccessor,并把之前的DelegatingMethodAccessorImpl引用替换为现在新创建的。下一次DelegatingMethodAccessorImpl就不会再交给NativeMethodAccessorImpl执行了,而是交给新生成的java字节码的MethodAccessor。
  

  

MethodAccessorGenerator使用了asm字节码动态加载技术,暂不深入研究只
  

  

总结,一个方法可以生成多个方法对象,但只有一个根对象,主要用于持有一个MethodAccessor对象,这个对象也可以认为一个方法只有一个,相当于是静态的。因为方法的调用是交给MethodAccessor执行的,所以我所想要知道的答案在MethodAccessor的调用中,深入MethodAccessor:,
  

  

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MethodAccessor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  假如有这么一个类,,

        公共类{   公共空间foo(字符串名称){   system . out。println(“你好,”+名字);   }   }      

可以编写另外一个类来反射调用一个上的方法:,

        进口java.lang.reflect.Method;   公开课TestClassLoad {   公共静态void main (String [] args){抛出异常   Class<& # 63;比;clz=forname (“A”);   对象o=clz.newInstance ();   m=clz方法。getMethod (" foo ", String.class);   for (int i=0;我& lt;16;我+ +){   m。调用(o, Integer.toString (i));   }   }   }      

注意到TestClassLoad类上不会有对类一个的符号依赖,也就是说在加载并初始化TestClassLoad类时不需要关心类一个的存在与否,而是等到主要()方法执行到调用forName()时才试图对类一个做动态加载;这里用的是一个参数版的forName(),也就是使用当前方法所在类的类加载器来加载,并且初始化新加载的类。……好吧这个细节跟主题没啥关系只

  

回到主题。这次我的测试环境是Sun的JDK 1.6.0更新13构建03。编译上述代码,并在执行TestClassLoad时加入- xx: + TraceClassLoading参数(或者- verbose: class或者直接- verbose都行),如下:
  

  

  

java  - xx: + TraTestClassLoad, ceClassLoading 

详解Java中方法的调用方法