Sorry for no updates for such long time, but I just had a lot of other problems. Posts should be now more often, but probably shorter.

Previous posts:
1. Introduction, primitives, random and modulo
2. For loops, lambdas, streams

In this post we will only focus on reflections, and some two interesting cases when using MethodHandles, we will test reflective access to both private and public fields, and how reflections/method handles performance can be affected if field that store MethodHandle/Field is static and/or final.
[Benchmark source code]

Raw results can be found in link above too, here I will only point most interesting cases.

Lets start with comparing normal reflections:

Benchmark                                                Mode  Cnt  Score   Error  Units
normalDirectAccess                                       avgt   10  2,867 ± 0,142  ns/op

somethingPublicFieldAccessor_nonAccessible_access        avgt   10  6,622 ± 0,422  ns/op
somethingPublicFieldAccessor_nonAccessible_static_access avgt   10  5,790 ± 0,177  ns/op
somethingPublicFieldAccessor_access                      avgt   10  6,106 ± 1,180  ns/op
somethingPublicFieldAccessor_static_access               avgt   10  4,840 ± 0,261  ns/op

somethingPrivateFieldAccessor_access                     avgt   10  5,397 ± 0,125  ns/op
somethingPrivateFieldAccessor_static_access              avgt   10  4,758 ± 0,122  ns/op
somethingPrivateFieldAccessor_static_final_access        avgt   10  4,739 ± 0,120  ns/op

From that we can see that static or final does not change much, the only difference between static and non-static is less time needed to fetch Field instance.
But we can see that .setAccessible gives small performance boost even when you don’t need to use it.
Also time between public and private access does not change much, seems to be this same. And direct access is 2/3x faster, nothing special here.

As public and private results are this same in all cases I wll now focus on private access only.

Now something more interesting, method handles:

Benchmark                                                Mode  Cnt  Score   Error  Units
somethingPrivateFieldAccessor_handle_access              avgt   10  5,831 ± 0,204  ns/op
somethingPrivateFieldAccessor_handle_bound_access        avgt   10  5,498 ± 0,175  ns/op

somethingPrivateFieldAccessor_static_handle_access       avgt   10  5,408 ± 0,202  ns/op
somethingPrivateFieldAccessor_static_handle_bound_access avgt   10  5,327 ± 0,265  ns/op

using .bind can also improve performance, and again, nothing special.

But… if we use static final MethodHandle = ... in our code something interesting happens:

Benchmark                                                      Mode  Cnt  Score   Error  Units
normalDirectAccess                                             avgt   10  2,867 ± 0,142  ns/op
somethingPrivateFieldAccessor_static_final_handle_access       avgt   10  2,827 ± 0,058  ns/op
somethingPrivateFieldAccessor_static_final_handle_bound_access avgt   10  2,859 ± 0,084  ns/op

JIT can optimize such MethodHandles much better than all other reflection, allowing to get this same performance as direct access, even on final fields!
It’s great and sad at this same time, as we can use reflections without any overhead, but only if we can construct MethodHandles in static blocks while loading class.

Final note

Benchmarks are created using JMH benchmark framework.
All code used for benchmarks can be found on GitHub: [Blog benchmarks]


If you want me to check something you can't understand, or explain some weird java behavior, feel free to e-mail me at: gotofinaldev@gmail.com or just write comment below!