Search code examples
javaperformancereflectionjava-8methodhandle

Why use reflection to access class members when MethodHandle is faster?


With the release of Java 7 came the MethodHandle, which allows a user to invoke a method as if using its underlying bytecode. In particular, the MethodHandles.Lookup class provides factory methods to create method handles to access class members:

The factory methods on a Lookup object correspond to all major use cases for methods, constructors, and fields. Each method handle created by a factory method is the functional equivalent of a particular bytecode behavior.

Functionally, this is more or less equivalent to using reflection to access these same class members, yet method handles are faster than reflection.

So, is there any reason to still use reflection functionalities like Field#get(..)/Method.invoke(..) or are these methods effectively obsolete with the introduction of the faster method handles?

Note that while method handles were introduced in Java 7, my question primarily pertains to Java 8, in which they were optimized to supposedly reach performance approximately equal to direct field/method calls, surpassing reflection's ability.


Solution

  • Reflection and method handles serve different purposes, and exist at different levels of abstraction. You should use the one that is right for the problem you are solving.

    Reflection is a general-purpose introspection mechanism, which includes many features that the method handle mechanism lacks, such as enumerating the members of a class (Class.getMethods()), inspecting the characteristics of a member such as its accessibility flags, inspecting generic signatures of members, etc.

    Additionally, reflective objects can be freely shared without granting access to the sharee, because the access checks are made at each invocation. On the other hand, sharing method handles confers to the sharee the capability to invoke. So they also have different security implications.

    Method handles are a low-level mechanism for finding, adapting, and invoking methods. While invocation through method handles is faster than through reflection (though to date, direct bytecode invocation is still generally faster than method handle invocation), method handles are also significantly harder to use, as they do not automatically perform the adaptations Java users would expect (such as converting a String argument to Object), resulting in linkage errors.

    The reflection library is aimed at mainstream Java users; the method handle layer is aimed more at compiler and language runtime writers. Pick the tool designed for the job.