34

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.

Community
  • 1
  • 1
FThompson
  • 28,352
  • 13
  • 60
  • 93
  • For more detail on method handles, see [MethodHandle - What is it all about?](http://stackoverflow.com/q/8823793/1247781) – FThompson Jun 06 '15 at 00:34
  • It doesn't look much faster, especially if you turn off access checking in reflection ( `setAccessible(true)` ) – ZhongYu Jun 06 '15 at 01:42
  • @bayou.io That sounds reasonable, but do you have any benchmark tests as evidence? Simply modifying the benchmark in the linked question to call `setAccessible(true)` and outputting those results would be evidence enough for me. – FThompson Jun 06 '15 at 01:57
  • @Vulcan - I don't, but the comments in that answer seem to imply that. And it would be surprising if reflection doesn't adopt the same optimization that MH does; there are tons of libraries using reflection, and it's java's best interest to optimize for them. – ZhongYu Jun 06 '15 at 02:35
  • 1
    also, it's reasonable to assume that most fields are not public accessible, and libraries need to break the access rules during reflection. – ZhongYu Jun 06 '15 at 02:37
  • @bayou.io If reflection and method handles indeed use the same optimization, that'd be a great answer to post to my question. I haven't been able to find anything indicating so, however. – FThompson Jun 06 '15 at 02:59
  • 3
    @Vulcan to be fair, your question is not completely consistent. On the one hand, you're asking if there is *any reason to still use reflection*, and would consider them *obsolete* if there is no such reason; on the other hand you're saying in the small print that you're mainly interested in performance. I think Brian Goetz answered your first question perfectly, and Elliot Frisch your second; but it would be better if your question indicated better what kind of answer you're really looking for. – Erwin Bolwidt Jun 06 '15 at 03:04
  • @ErwinBolwidt The focus is on why the reflection methods of `Field#get/set` and `Method#invoke` would still be used, when method handles offer a (supposedly) faster alternative. Of course, if other reflection tools are better for a given job, it'd make sense to use those methods then, but are there cases (regarding these methods) in which reflection would be the preferable choice over method handle? I believe the body of my question is quite clear, but I've edited the title to better reflect the focus on performance. If you still believe it's unclear, I'm open to suggestions. – FThompson Jun 06 '15 at 03:10
  • @ErwinBolwidt If it wasn't clear, I'm not asking if reflection is obsolete; I'm asking if those specific methods are obsolete given the better alternative in method handles. – FThompson Jun 06 '15 at 03:11
  • I wonder, how does it compare to other technics, like "Unsafe", or runtime bytecode generation. – ZhongYu Jun 06 '15 at 03:17

2 Answers2

45

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.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
  • While this answer is helpful, my question is only pertaining to the use of `Field#get/set` and `Method#invoke` to access/invoke class members, and whether there's any reason to still use these reflections methods when method handles provide supposedly faster ways to achieve the same access/invocation. – FThompson Jun 06 '15 at 02:53
  • 11
    Performance is not the only measure of suitability for a task. Method handles are faster, but they're less flexible and harder to use. Maybe method handles are the right tool for your problem (you haven't really explained it), maybe they're not. But your question was, "Why use reflection when we have method handles". And there are many reasons why you might prefer reflection, other than invocation performance. – Brian Goetz Jun 06 '15 at 02:58
  • "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)" Hope Java solves this problem in near future. – user1870400 Apr 30 '19 at 08:05
  • 1
    @user1870400 The problem is a bit more in-depth. MethodHandles use a lot of tricks to get fast - and one of those tricks is that `MethodHandle.invokeExact` is signature poymorphic. This means, the arguments and return types are stored in the compiled class as they appear in the source. So `int result = (int) mh.invokeExact("foo");` will record a signature of `(Ljava/lang/String;)I`. `invokeExact` will throw if the signature does not EXACTLY match the type of the MethodHandle. – Johannes Kuhn Dec 08 '20 at 16:00
3

tl;dr No. You should use (and prefer) MethodHandles to the Core Reflection API when you can.

MethodHandles.Lookup access says (in part),

Unlike with the Core Reflection API, where access is checked every time a reflective method is invoked, method handle access checking is performed when the method handle is created.

Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • @BrianGoetz Did you miss *my question primarily pertains to their performance in Java 8, in which they were optimized to supposedly reach performance approximately equal to direct field/method calls*? – Elliott Frisch Jun 06 '15 at 02:43
  • 3
    "performance **in Java 8**", as opposed to performance in Java 7, not "primarily ... performance". – a better oliver Jun 06 '15 at 08:09
  • 4
    This answer makes a dangerously wrong assumption: that invocation performance is the only measure of fitness for the task. Method handles are faster, but they're designed for a different purpose, aimed at a very different audience, don't do everything reflection does, and are less flexible and harder to use. There are many reasons why you might prefer reflection, other than invocation performance. – Brian Goetz Dec 18 '19 at 16:09