java 反射真的慢吗?

大家似乎有个默认的常识:java的反射性能不好,应该使用asm、cglib之类的库替代。

看java的反射实现会有两种情况,参考NativeMethodAccessorImpl

1.调用native方法,涉及到方法查找,

2.生成字节码,动态加载类,使用MethodAccessorGenerator

就是说在调用次数超过阈值15之后,就会动态生成类,来执行反射方法,本质上和直接调用时一样的。动态生成类的模式和cglib也是一样的。

跑了几个测试看看,计算的平均每次用时,用的mac jdk8,jvm参数:-server -Xmx4g -Xms4g -Xmn512m  -Xss256k -verbose:gc (原来想贴一下代码的,简书的“引用”实在太难用了) 

循环次数    1000    10*1000   100*1000     1000*1000

cglib      1392ns    984ns      228ns              78ns

反射        4753ns  980ns        163ns              36ns


从测试结果看出来,次数越多,反射的性能越好,这是为什么呢?和jit编译有关,使用-XX:+PrintCompilation可以看到,循环次数到达1000*1000的时候,不仅编译层数达到了4,而且发生了OSR编译(栈上替换),运行在OSR代码中的次数越多,性能越好。

同样的cglib的FastClass也会发生jit编译,也会使用OSR编译,但是性能比不过反射,同时通过监控内存,发现cglib使用的内存也比较多,主要是动态生成类的代码不一样。

cglib的FastClass是针对一个类动态生成一个新的类;反射是针对每一个方法生成一个新的类,方法体比较小,更适合jit做动态编译、内联。

加上-XX:+PrintInlining 参数,看内联的情况,反射的方法都经过了内联优化,而使用cglib生成的代码无法内联,容易出现hot method too big的情况。

查看cglib代码可以通过System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"./");将动态生成的代码保存到文件。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 这篇文章是我之前翻阅了不少的书籍以及从网络上收集的一些资料的整理,因此不免有一些不准确的地方,同时不同JDK版本的...
    高广超阅读 15,825评论 3 83
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,421评论 11 349
  • java编译器,java解释器 1.java程序是一种可跨平台执行的语言,之所以可以跨平台,是因为jvm的存在,J...
    rabbit_coding阅读 7,061评论 2 18
  • Ivy艾薇老师,中文名欧亚思,89年的年轻宝妈一枚,宝贝4岁啦…… 来杭州两年半,定居三墩金地板块,是一枚崭新而又...
    做自己Ivy阅读 1,037评论 0 1
  • I need you。
    蓬蓬蓬的毛毛熊阅读 145评论 0 0