当你去正常的实例化一个对象的时候,和你反射出一个对象的时候,你会发现,后者比前者要慢很多很多.

这是为什么呢?

有外国网友在反射的性能上做了一个简单的测试,C#版本

反射的性能测试

原代码链接:Tests performance of Reflection · GitHub

用反射做的基本事情做了一些性能测试

这些测试案例是:


- 创建一个对象
- 调用一个有两个参数的方法
- 设置一个对象的4个属性

他实现了有反射和无反射的每个测试案例,这样我就可以比较结果。在测试中,使用了ObjectDataSource教程中的Product和ProductDAL类,只是在ProductDAL类中修改了一个新方法。每个测试案例都重复了100万次,以获得更准确的数值。测试是在1GB内存的AMD 3200上进行的。测试的源代码可以在这篇文章的最后找到。

得到的结果是:

创建一个对象 -> 使用反射慢了6倍
调用方法 -> 使用反射慢了143倍
设置属性 -> 使用反射慢了14倍

测试程序产生的全部输出结果是:

构造器
省略的时间:间隔:0,074104秒

使用反射的构造函数
耗时:间隔:0,449345秒

方法调用
耗时:间隔:0,025408秒

使用反射的方法调用
省略的时间:间隔。3,631799秒

设置属性
省略时间:间隔:1,562256秒

使用反射设置属性
省略时间:间隔:22,492780秒


既然我们知道反射会很慢,那么我们接着进行分析

首先我们先参考Oracle的reflect官方文档

https://docs.oracle.com/javase/tutorial/reflect/index.html

Drawbacks of Reflection

Performance Overhead

Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.

翻译上述文字如下:

反射的弊端:

性能开销:
因为反射涉及到动态解析的类型,所以某些Java虚拟机的优化不能被执行。因此,反射操作的性能比非反射操作的性能要慢,应该避免在对性能敏感的应用程序中频繁调用的代码部分。 

我们搬运Stackoverflow的一个回答(作者 oxbow_lakes著):

反射是缓慢的,有几个明显的原因:

  1. 编译器不能做任何优化,因为它不能真正了解你在做什么。这可能也适用于JIT
  2. 所有被调用/创建的东西都必须被发现(例如,通过名称查找类,查找匹配的方法等等)。
  3. 参数需要通过装箱/拆箱、打包成数组、用InvocationTargetExceptions包住异常并重新抛出等方式进行包装。

反射虽然慢,但与解析XML或访问数据库相比,反射的开销可能显得微不足道。

另一点要记住的是,对于确定某样东西在实践中有多快,微观测试是一种出了名的有缺陷的机制。正如Tim Bender所说的,JVM需要时间来 "预热",JIT可以对代码热点进行即时重新优化等等。

与非反射性代码相比,它的速度较慢。重要的不是它是否慢,而是它是否在重要的地方慢。例如,如果你在网络环境中使用反射来实例化对象预期并发量可能会上升到10K那么它就会很慢

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐