ImageVerifierCode 换一换
格式:DOCX , 页数:22 ,大小:27.63KB ,
资源ID:28616704      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/28616704.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(invoke 用法.docx)为本站会员(b****8)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

invoke 用法.docx

1、invoke 用法在写代码的时候,发现Method可以调用子类的对象,但子类即使是改写了的Method,方法名一样,去调用父类的对象也会报错,虽然这是很符合多态的现象,也符合java的动态绑定规范,但还是想弄懂java是如何实现的,就学习了下Method的源代码。 Method的invoke方法1.先检查 AccessibleObject的override属性是否为true。AccessibleObject是Method,Field,Constructor的父类,override属性默认为false,可调用setAccessible方法改变,如果设置为true,则表示可以忽略访问权限的限制,直

2、接调用。2.如果不是ture,则要进行访问权限检测。用Reflection的quickCheckMemberAccess方法先检查是不是public的,如果不是再用Reflection.getCallerClass(1)方法获得到调用这个方法的Class,然后做是否有权限访问的校验,校验之后缓存一次,以便下次如果还是这个类来调用就不用去做校验了,直接用上次的结果,(很奇怪用这种方式缓存,因为这种方式如果下次换个类来调用的话,就不用会缓存了,而再验证一遍,把这次的结果做为缓存,但上一次的缓存结果就被冲掉了。这是一个很简单的缓冲机制,只适用于一个类的重复调用)。3.调用MethodAccessor

3、的invoke方法。每个Method对象包含一个root对象,root对象里持有一个MethodAccessor对象。我们获得的Method独享相当于一个root对象的镜像,所有这类Method共享root里的MethodAccessor对象,(这个对象由ReflectionFactory方法生成,ReflectionFactory对象在Method类中是static final的由native方法实例化)。ReflectionFactory生成MethodAccessor:如果noInflation的属性为true则直接返回MethodAccessorGenerator创建的一个Method

4、Accessor。否则返回DelegatingMethodAccessorImpl,并将他与一个NativeMethodAccessorImpl互相引用。但DelegatingMethodAccessorImpl执行invoke方法的时候又委托给NativeMethodAccessorImpl了。再一步深入4.NativeMethodAccessorImpl的invkoe方法:调用natiave方法invoke0执行方法调用.注意这里有一个计数器numInvocations,每调用一次方法+1,当比 ReflectionFactory.inflationThreshold(15)大的时候,用M

5、ethodAccessorGenerator创建一个MethodAccessor,并把之前的DelegatingMethodAccessorImpl引用替换为现在新创建的。下一次DelegatingMethodAccessorImpl就不会再交给NativeMethodAccessorImpl执行了,而是交给新生成的java字节码的MethodAccessor。MethodAccessorGenerator使用了asm字节码动态加载技术,暂不深入研究。总结 一个方法可以生成多个Method对象,但只有一个root对象,主要用于持有一个MethodAccessor对象,这个对象也可以认为一个方法

6、只有一个,相当于是static的。因为Method的invoke是交给MethodAccessor执行的,所以我所想要知道的答案在MethodAccessor的invoke中,深入MethodAccessor:-MethodAccessor-假如有这么一个类A: public class A public void foo(String name) System.out.println(Hello, + name);可以编写另外一个类来反射调用A上的方法: import java.lang.reflect.Method;public class TestClassLoad public sta

7、tic void main(String args) throws Exception Class clz = Class.forName(A);Object o = clz.newInstance();Method m = clz.getMethod(foo, String.class);for (int i = 0; i 16; i+) m.invoke(o, Integer.toString(i);注意到TestClassLoad类上不会有对类A的符号依赖也就是说在加载并初始化TestClassLoad类时不需要关心类A的存在与否,而是等到main()方法执行到调用Class.forNa

8、me()时才试图对类A做动态加载;这里用的是一个参数版的forName(),也就是使用当前方法所在类的ClassLoader来加载,并且初始化新加载的类。好吧这个细节跟主题没啥关系。 回到主题。这次我的测试环境是Sun的JDK 1.6.0 update 13 build 03。编译上述代码,并在执行TestClassLoad时加入-XX:+TraceClassLoading参数(或者-verbose:class或者直接-verbose都行),如下:控制台命令java -XX:+TraTestClassLoad ceClassLoading 可以看到输出了一大堆log,把其中相关的部分截取出来如

9、下:Loaded TestClassLoad from file:/D:/temp_code/test_java_classload/Loaded A from file:/D:/temp_code/test_java_classload/Loaded sun.reflect.NativeMethodAccessorImpl from shared objects fileLoaded sun.reflect.DelegatingMethodAccessorImpl from shared objects fileHello, 0Hello, 1Hello, 2Hello, 3Hello, 4

10、Hello, 5Hello, 6Hello, 7Hello, 8Hello, 9Hello, 10Hello, 11Hello, 12Hello, 13Hello, 14Loaded sun.reflect.ClassFileConstants from shared objects fileLoaded sun.reflect.AccessorGenerator from shared objects fileLoaded sun.reflect.MethodAccessorGenerator from shared objects fileLoaded sun.reflect.ByteVe

11、ctorFactory from shared objects fileLoaded sun.reflect.ByteVector from shared objects fileLoaded sun.reflect.ByteVectorImpl from shared objects fileLoaded sun.reflect.ClassFileAssembler from shared objects fileLoaded sun.reflect.UTF8 from shared objects fileLoaded java.lang.Void from shared objects

12、fileLoaded sun.reflect.Label from shared objects fileLoaded sun.reflect.Label$PatchInfo from shared objects fileLoaded java.util.AbstractList$Itr from shared objects fileLoaded sun.reflect.MethodAccessorGenerator$1 from shared objects fileLoaded sun.reflect.ClassDefiner from shared objects fileLoade

13、d sun.reflect.ClassDefiner$1 from shared objects fileLoaded sun.reflect.GeneratedMethodAccessor1 from _JVM_DefineClass_Hello, 15可以看到前15次反射调用A.foo()方法并没有什么稀奇的地方,但在第16次反射调用时似乎有什么东西被触发了,导致JVM新加载了一堆类,其中就包括Loaded sun.reflect.GeneratedMethodAccessor1 from _JVM_DefineClass_这么一行。这是哪里来的呢? 先来看看JDK里Method.invo

14、ke()是怎么实现的。 java.lang.reflect.Method: public final class Method extends AccessibleObject implements GenericDeclaration, Member / . private volatile MethodAccessor methodAccessor; / For sharing of MethodAccessors. This branching structure is / currently only two levels deep (i.e., one root Method and

15、 / potentially many Method objects pointing to it.) private Method root; / . public Object invoke(Object obj, Object. args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException if (!override) if (!Reflection.quickCheckMemberAccess(clazz, modifiers) Class caller = Reflec

16、tion.getCallerClass(1); Class targetClass = (obj = null | !Modifier.isProtected(modifiers) ? clazz : obj.getClass(); boolean cached; synchronized (this) cached = (securityCheckCache = caller) & (securityCheckTargetClassCache = targetClass); if (!cached) Reflection.ensureMemberAccess(caller, clazz, o

17、bj, modifiers); synchronized (this) securityCheckCache = caller; securityCheckTargetClassCache = targetClass; if (methodAccessor = null) acquireMethodAccessor(); return methodAccessor.invoke(obj, args); / NOTE that there is no synchronization used here. It is correct / (though not efficient) to gene

18、rate more than one MethodAccessor / for a given Method. However, avoiding synchronization will / probably make the implementation more scalable. private void acquireMethodAccessor() / First check to see if one has been created yet, and take it / if so MethodAccessor tmp = null; if (root != null) tmp

19、 = root.getMethodAccessor(); if (tmp != null) methodAccessor = tmp; return; / Otherwise fabricate one and propagate it up to the root tmp = reflectionFactory.newMethodAccessor(this); setMethodAccessor(tmp); / .可以看到Method.invoke()实际上并不是自己实现的反射调用逻辑,而是委托给sun.reflect.MethodAccessor来处理。 每个实际的Java方法只有一个对应

20、的Method对象作为root,。这个root是不会暴露给用户的,而是每次在通过反射获取Method对象时新创建Method对象把root包装起来再给用户。在第一次调用一个实际Java方法对应得Method对象的invoke()方法之前,实现调用逻辑的MethodAccessor对象还没创建;等第一次调用时才新创建MethodAccessor并更新给root,然后调用MethodAccessor.invoke()真正完成反射调用。 那么MethodAccessor是啥呢? sun.reflect.MethodAccessor:public interface MethodAccessor /*

21、 Matches specification in link java.lang.reflect.Method */ public Object invoke(Object obj, Object args) throws IllegalArgumentException, InvocationTargetException;可以看到它只是一个单方法接口,其invoke()方法与Method.invoke()的对应。 创建MethodAccessor实例的是ReflectionFactory。sun.reflect.ReflectionFactory:public class Reflecti

22、onFactory private static boolean initted = false; / . / / Inflation mechanism. Loading bytecodes to implement / Method.invoke() and Constructor.newInstance() currently costs / 3-4x more than an invocation via native code for the first / invocation (though subsequent invocations have been benchmarked

23、 / to be over 20x faster). Unfortunately this cost increases / startup time for certain applications that use reflection / intensively (but only once per class) to bootstrap themselves. / To avoid this penalty we reuse the existing JVM entry points / for the first few invocations of Methods and Cons

24、tructors and / then switch to the bytecode-based implementations. / / Package-private to be accessible to NativeMethodAccessorImpl / and NativeConstructorAccessorImpl private static boolean noInflation = false; private static int inflationThreshold = 15; / . /* We have to defer full initialization o

25、f this class until after the static initializer is run since java.lang.reflect.Methods static initializer (more properly, that for java.lang.reflect.AccessibleObject) causes this classs to be run, before the system properties are set up. */ private static void checkInitted() if (initted) return; Acc

26、essController.doPrivileged(new PrivilegedAction() public Object run() / Tests to ensure the system properties table is fully / initialized. This is needed because reflection code is / called very early in the initialization process (before / command-line arguments have been parsed and therefore / th

27、ese user-settable properties installed.) We assume that / if System.out is non-null then the System class has been / fully initialized and that the bulk of the startup code / has been run. if (System.out = null) / java.lang.System not yet fully initialized return null; String val = System.getPropert

28、y(sun.reflect.noInflation); if (val != null & val.equals(true) noInflation = true; val = System.getProperty(sun.reflect.inflationThreshold); if (val != null) try inflationThreshold = Integer.parseInt(val); catch (NumberFormatException e) throw (RuntimeException) new RuntimeException(Unable to parse

29、property sun.reflect.inflationThreshold). initCause(e); initted = true; return null; ); / . public MethodAccessor newMethodAccessor(Method method) checkInitted(); if (noInflation) return new MethodAccessorGenerator(). generateMethod(method.getDeclaringClass(), method.getName(), method.getParameterTy

30、pes(), method.getReturnType(), method.getExceptionTypes(), method.getModifiers(); else NativeMethodAccessorImpl acc = new NativeMethodAccessorImpl(method); DelegatingMethodAccessorImpl res = new DelegatingMethodAccessorImpl(acc); acc.setParent(res); return res; 这里就可以看到有趣的地方了。如注释所述,实际的MethodAccessor实现有两个版本,一个是Java实现的,另一个是native code实现的。Java实现的版本在初始化时需要较多时间,但长久来说性能较好;native版本正好相反,启动时相对较快,但运行时间长了之后速度就比不过Java版了。这是HotSpot的优化方式带来的

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1