为什么Method访问看起来比Field访问快?

我正在做一些测试,以找出使用getter / setter和直接字段访问之间的速度差异。 我写了一个简单的基准测试应用程序:

public class FieldTest { private int value = 0; public void setValue(int value) { this.value = value; } public int getValue() { return this.value; } public static void doTest(int num) { FieldTest f = new FieldTest(); // test direct field access long start1 = System.nanoTime(); for (int i = 0; i < num; i++) { f.value = f.value + 1; } f.value = 0; long diff1 = System.nanoTime() - start1; // test method field access long start2 = System.nanoTime(); for (int i = 0; i < num; i++) { f.setValue(f.getValue() + 1); } f.setValue(0); long diff2 = System.nanoTime() - start2; // print results System.out.printf("Field Access: %d ns\n", diff1); System.out.printf("Method Access: %d ns\n", diff2); System.out.println(); } public static void main(String[] args) throws InterruptedException { int num = 2147483647; // wait for the VM to warm up Thread.sleep(1000); for (int i = 0; i < 10; i++) { doTest(num); } } } 

每当我运行它时,我都会得到一致的结果,例如: http : //pastebin.com/hcAtjVCL

我想知道是否有人可以向我解释为什么字段访问似乎比getter / setter方法访问慢,以及为什么最后8次迭代执行得非常快。


编辑 :考虑到assyliasStephen C评论后,我已将代码更改为http://pastebin.com/Vzb8hGdc ,其结果略有不同: http : //pastebin.com/wxiDdRix 。

解释是你的基准被打破了。

第一次迭代使用解释器完成。

 Field Access: 1528500478 ns Method Access: 1521365905 ns 

第二次迭代由解释器完成,然后我们翻转运行JIT编译代码。

 Field Access: 1550385619 ns Method Access: 47761359 ns 

剩余的迭代都是使用JIT编译代码完成的。

 Field Access: 68 ns Method Access: 33 ns etcetera 

它们令人难以置信的快速原因是JIT编译器已经优化了循环 。 它已经检测到它们没有对计算做出任何有用的贡献。 (目前尚不清楚为什么第一个数字似乎始终比第二个更快,但我怀疑优化的代码是以任何有意义的方式测量字段与方法访问。)


重新编写UPDATED代码/结果:显然JIT编译器仍在优化循环。