首页 > 编程知识 正文

java的反射机制原理,通俗理解java反射

时间:2023-05-05 13:55:39 阅读:15422 作者:490

接下来,从源代码的角度探究Java反射的实现原理吧。

publicclassreflectiontest { privatestaticintcount=0; publicstaticvoidfoo ({ new exception ) ) count ) '次)打印堆栈跟踪); } publicstaticvoidmain (字符串[ ] args ) Throwsexception ) class? clz=class.forname (reflection test ); 方法方法=clz.get方法(' foo ); for(intI=0; i20; I({method.invoke ) ) null; } }

下面的堆栈执行结果显示,从第17次开始,函数调用方式发生了变化

java.lang.Exception: 16次atcom.reflection.foo (reflection.Java :13 ) at sun.reflect.nativemethodaccessorimpption at sun.reflect.delegatingmethodaccessorimpl.invoke (delegatingmethodaccessorimpl.Java :43 ) at Java.lang.reflect 36020 ) java.lang.Exception: 17次atcom.reflection.foo ) reflection.exception.3360 at sun.reflect.generatedmethed at sun.reflect.delegatingmethodaccessorimpl.invoke (delegatingmethodaccessorimpl.Java :43 ) at Java.lang.reflect

@ callersensitivepublicobjectinvoke (objectobj,Object. args ) throws IllegalAccessException,IllegalArgumentException reflection.quickcheckmemberaccess (clazz,modifiers ) ) { Class? caller=reflection.getcallerclass (; checkaccess(caller、clazz、obj、modifiers ); } methodaccessorma=method accessor; //readvolatileif(ma==null ) { ma=acquireMethodAccessor ); }returnma.invoke(obj,args ); }通过方法访问器的invoke函数,可以看到方法访问器是实现以下:代码的接口

publicinterfacemethodaccessor {对象invoke (objectvar 1,Object[] var2) throws IllegalArgumentException, invocationtargeption method accessorimpl、MethodAccessorImpl、NativeMethodAccessorImpl三个实现类通过堆栈前16次调用的实现类NativeMethodAccessorImpl,然后调用的是GeneratedMethodAccessor1,接下来是NativeMethodAccessorImpl实现类

classnativemethodaccessorimplextendsmethodaccessorimpl { privatefinalmethodmethod; 隐私保护方法; 私有int num invocations; nativemethodaccessorimpl (method var1) { this.method=var1; }publicobjectinvoke(objectvar1,Object[] var2) throws IllegalArgumentException, invocationtargetexception { if (this.) this () ) ) 65 reflect util.isvmanonymousclass (this.method.getdeclaclass ) orimpl ) ) methodaccessorimpl.generate method (this.method.getdeclaringclass )、this.method.getName )、this. }returninvoke0(this.method,var1,var2); } void setparent (delegatingmethodaccessorimplvar1) { this.parent=var1; }隐私保护对象jectinvoke0(方法var 0,对象var 1,对象[ ] var2); }你会发现在调用方法的过程中有条件判断

this.numinvocationsreflectionfactory.inflation threshold (

在此阈值内时调用invoke0方法。 这是一个朴素函数,在超过该阈值后生成MethodAccessorGenerator对象,然后通过ASM生成新的sun.reflect.generatedmethodaccessor 1类。 可以使用arthas工具

publicclassgeneratedmethodaccessor 1扩展内存访问sorimpl { @ overridepublicobjectinvoke (objectobj,Object[] args ) the }那么,为什么要设置阈值来调用这两种方法呢? 其实这是基于性能的考虑,JNI native调用的方式比动态生成类调用的方式慢20倍左右。 但是,由于第一个字节码生成过程很慢,因此如果只调用一次反射,则采用生成字节码的方式反而比native调用的方式慢3-4倍。 因此,Java引入了inflation机制,当调用次数小于阈值时,采用朴素方法,没有额外的类生成、验证和加载开销; 如果超过阈值,则使用ASM生成新类,以确保后续调用比native快。

参考书籍:

lgdcjl. Offer来了[M] .北京:电子工业出版社,2020

听歌茉莉JVM字节码[M] .北京:机械工业出版社,2020年。

关注微信通信公众号: IT技术发展之路

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。