Java 反射方法调用比字段更快地产生结果?

标签 java performance reflection

我正在对一些代码进行微基准测试(请保持友善)并遇到了这个难题:使用反射读取字段时,调用 getter 方法比读取字段更快。

简单的测试类:

private static final class Foo {
    public Foo(double val) {
        this.val = val;
    }
    public double getVal() { return val; }
    public final double val; // only public for demo purposes
}

我们有两个反射(reflection):

Method m = Foo.class.getDeclaredMethod("getVal", null);
Field  f = Foo.class.getDeclaredField("val");

现在我在一个循环中调用这两个反射,invoke 在 Method 上,get 在 Field 上。第一次运行是为了预热 VM,第二次运行是通过 10M 次迭代完成的。 方法调用始终快 30%,但为什么呢?请注意,getDeclaredMethod 和 getDeclaredField 不会在循环中调用。它们被调用一次并在循环中的同一个对象上执行。

我还尝试了一些小的变化:使字段成为非最终的、可传递的、非公开的,等等。所有这些组合导致了统计上相似的性能。

编辑:这是在 WinXP、Intel Core2 Duo、Sun JavaSE build 1.6.0_16-b01 上,在 jUnit4 和 Eclipse 下运行。

最佳答案

我有根据的猜测是 getDeclaredField 和 getDeclaredMethod 的实现方式不同:每次调用时,getDeclaredField 都必须检查变量类型和大小,以便返回实际对象或原始类型,getDeclaredMethod 会将指针返回到同一个方法,该方法静态处理所有其余部分。

编辑:

我的解释是类似的:对于每个类,一个方法在内存中只包含一次,而每个对象实例可以有不同的属性值。当您通过执行方法调用(仍然仅使用方法指针)获取属性值时,编译器已经优化了访问参数的方法,知道确切的类层次结构等,而当您通过使用“get”获取属性值时",你让反射完成 getter 方法的工作,显然没有编译器优化。

关于Java 反射方法调用比字段更快地产生结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4593165/

相关文章:

php - 在 while 循环内加速 mysql 查询

java - 将 Integer ArrayList 作为 Intent 额外发送的最佳方式?

c# - 为什么反射仍然有效时动态方法调用失败?

java - 如果 Spring Batch 中事务失败,如何停止 JpaItemWriter?

java - 在 Android 中将 byte[] 渲染为位图

java - Android 示例无法编译

c++ - 我怎样才能使这个算法的内存效率更高?

java - 为什么反射慢?

.net - 构造 ArgumentException 时如何以编程方式确定参数名称?

java - OpenClover 如何计算分支数?