Java反射的性能问题

Java反射的性能问题

反射是Java一个很重要的动态特性,许多常用框架都用到了Java的反射。想要详细了解一下Java的反射相比直接调用有多少的性能损耗,效率降低的原因在哪里,以及如何对反射进行优化,自己总结了一下。

1 反射有哪些方法?

老生常谈了,三种方法,分别是:

  1. .class字段

    Foo foo = new Foo();
    Class c1 = foo.class;
    
  2. getClass()方法

    Foo foo = new Foo();
    Class c2 = foo.getClass();
    
  3. forName()方法

    Foo foo = new Foo();
    Class c3 = Class.forName("Foo的包路径");
    

得到Class对象之后,可以通过newInstance()的方法创建新的实例:

Foo newIns = c1.newInstance();

2 反射的效率损失?

这里直接放上反射的性能问题这篇Blog里的实验数据:

场景本机测试结果(XP,双核,2G)服务器测试结果(Linux,XEN虚拟机,8核,5.5G)
方法直接调用235MS190MS
JDK Method调用29188MS4633MS
JDK Method调用(稍作优化)5672MS4262MS
Cglib FastMethod调用5390MS2787MS

可以看到,即使是经过优化,反射仍然比直接调用要慢上一个数量级。

3 影响反射效率的原因?

那么反射效率低的原因在哪里呢?这个问题网上一直说的含糊不清,应该是和每个版本Java的反射的具体实现方式有关。实际上,Java对反射在不断地进行优化,反射的性能一直在提高。

Java反射获取方法

流程是这样的:

  • 反射需要获取类的所有方法,得到一个Method数组,包含着每个方法的参数,返回值类型,权限等信息;

  • 需要遍历Method数组,得到我们需要调用的那个方法,返回其拷贝,接下来我们调用其拷贝;

  • 通过invoke来调用拷贝的方法,在调用之前,我们要先检查是否有权限执行该方法;

  • 调用方法需要对参数进行解封,因为invoke的参数类型为Object,需要将其解封为实际的参数类型;

  • 反射需要动态加载,因而无法对其进行即时(JIT)优化。

反射的效率损失主要集中在以上几个方面。

4 如何进行优化?

针对以上几点,主要的优化方法有:

  • 利用缓存,将反射得到的元数据缓存起来,使用时直接从内存中访问。
  • 不要用getMethods()方法后再遍历,直接用getMethod(methodName)来根据方法名获取方法。
  • 使用高性能的反射库
  • setAccessible(true),禁用安全检查,这会提升很大的效率

实际上,随着JDK版本的优化,很多工作无需我们自己做,大多数情况下,只需要手动设置setAccessible(true)即可实现反射的高性能。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值