欢迎大家来到IT世界,在知识的湖畔探索吧!
查阅Method.invoke的源代码发现,它实际上委派给MethodAccessor来处理。MethodAccessor是一个接口,它有两个已有的具体实现:
1、一个通过本地方法来实现反射调用(本地实现)
2、另一个则使用了委派模式。(委派实现)
每一个Method实例的第一次反射调用都会生成一个委派实现,它所委派的具体实现便是一个本地实现。本地实现非常容易理解。当进入了Java虚拟机内部之后,我们便拥有了Method实例所指向方法的具体地址。
反射调用先是调用了Method.invoke,然后进入委派实现(DelegatingMethodAccessorImpl),再然后进入本地实现(NativeMethodAccesssorImpl),最后到达目标方法。
为什么反射调用还要采取委派实现作为中间层?
java的反射调用机制还设立了另外一种动态生成字节码的实现(动态实现),直接使用invoke指令来调用目标方法。之所以采用委派实现,便是为了能够在本地实现和动态实现中切换。
动态实现和本地实现相比,其运行效率要快上20倍。这是因为动态实现无需经过Java到C++再到Java的切换,但由于生成字节码十分耗时,仅调用一次的话,反而是本地实现要快上3到4倍。
Infaltion(膨胀)
考虑到许多反射调用仅会执行一次,Java虚拟机设置了一个阈值15(可以通过-Dsun.reflect.inflationThreshold = 来调整),当某个反射调用的调用次数在15之下时,采用本地实现;当达到15时,便开始动态生成字节码,并将委派实现的委派对象切换至动态实现,这个过程我们称之为Inflation。
反射调用的Inflation机制是可以通过参数(-Dsun.reflect.noInflation=true)来关闭的。这样一来,在反射调用一开始便会直接生成动态实现,而不会使用委派实现或者本地实现。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/17668.html