Java reflection Method invocations yield result faster than Fields?
I was microbenchmarking some code (please be nice) and came across this puzzle: when reading a field using reflection, invoking the getter Method is faster than reading the Field.
Simple test class:
private static final class Foo {
public Foo(double val) {
this.val = val;
}
publ开发者_如何转开发ic double getVal() { return val; }
public final double val; // only public for demo purposes
}
We have two reflections:
Method m = Foo.class.getDeclaredMethod("getVal", null);
Field f = Foo.class.getDeclaredField("val");
Now I call the two reflections in a loop, invoke
on the Method, and get
on the Field. A first run is done to warm up the VM, a second run is done with 10M iterations. The Method invocation is consistently 30% faster, but why? Note that getDeclaredMethod and getDeclaredField are not called in the loop. They are called once and executed on the same object in the loop.
I also tried some minor variations: made the field non-final, transitive, non-public, etc. All of these combinations resulted in statistically similar performance.
Edit: This is on WinXP, Intel Core2 Duo, Sun JavaSE build 1.6.0_16-b01, running under jUnit4 and Eclipse.
My educated guess would be a difference in how getDeclaredField and getDeclaredMethod are implemented: While each time it is called, getDeclaredField would have to check for the variable type and size, in order to return an actual object or primitive type, getDeclaredMethod would return the pointer to one and the same method, which takes care of all the rest statically.
Edit:
My explanation is similar: A method is contained in memory only once for each class, while each object instance can have different property values. When you get the property value by executing a method call (still using only the method pointer), the compiler has optimized the method to access the parameter, knowing the exact class hierarchy etc., while when you get the property's value by using "get", you let reflections do the getter method's job, and there can obviously be no compiler optimization.
In your microbenchmark, the method invocation is faster because of optimizations made by the JVM/Hotspot with in your loop.
Change your microbenchmak:
Make a loop in which: read the value by Reflection, then increase 1 (for instance), and then assign to the same Field via Reflection. And outside the loop, make a final read and System.out.println it...
Execute the two variants (Field vs Method) and you will see that the real difference is just the opposite: Method invocations are actually 30-40% slower.
Regards
does this also imply thatdouble d = Foo.getVal()
is 30% faster than double d = Foo.val
?
精彩评论