java 反射 慢_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,"./");将动态生成的代码保存到文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值