Question

I am studying new features of JDK 1.7 and I just can't get it what MethodHandle is designed for? I understand (direct) invocation of the static method (and use of Core Reflection API that is straightforward in this case). I understand also (direct) invocation of the virtual method (non-static, non-final) (and use of Core Reflection API that requires going through Class's hierarchy obj.getClass().getSuperclass()). Invocation of non-virtual method can be treated as special case of the former one.

Yes, I aware that there is an issue with overloading. If you want to invoke method you have to supply the exact signature. You can't check for overloaded method in easy way.

But, what is MethodHandle about? Reflection API allows you to "look on" the object internals without any pre-assumption (like implemented the interface). You can inspect the object for some purpose. But what is MethodHandle is designed too? Why and when should I use it?

UPDATE: I am reading now this http://blog.headius.com/2008/09/first-taste-of-invokedynamic.html article. According to it, the main goal is to simplify life for scripting languages that runs atop of JVM, and not for Java Language itself.

UPDATE-2: I finish to read the link above, some quotation from there:

The JVM is going to be the best VM for building dynamic languages, because it already is a dynamic language VM. And InvokeDynamic, by promoting dynamic languages to first-class JVM citizens, will prove it.

Using reflection to invoke methods works great...except for a few problems. Method objects must be retrieved from a specific type, and can't be created in a general way.<...>

...reflected invocation is a lot slower than direct invocation. Over the years, the JVM has gotten really good at making reflected invocation fast. Modern JVMs actually generate a bunch of code behind the scenes to avoid a much of the overhead old JVMs dealt with. But the simple truth is that reflected access through any number of layers will always be slower than a direct call, partially because the completely generified "invoke" method must check and re-check receiver type, argument types, visibility, and other details, but also because arguments must all be objects (so primitives get object-boxed) and must be provided as an array to cover all possible arities (so arguments get array-boxed).

The performance difference may not matter for a library doing a few reflected calls, especially if those calls are mostly to dynamically set up a static structure in memory against which it can make normal calls. But in a dynamic language, where every call must use these mechanisms, it's a severe performance hit.

http://blog.headius.com/2008/09/first-taste-of-invokedynamic.html

So, for Java programmer it is essentially useless. Am I right? From this point of view, It can be only considered as alternative way for Core Reflection API.

UPDATE-2020: Indeed, MethodHandle can be thought as s more powerful alternative to Core Reflection API. Starting with JDK 8 there are also Java Language features that use it.

Était-ce utile?

La solution 4

Almost 9 years past since I've asked this question. JDK 14 is last stable version that has massive usage of MethodHandle... I've create mini-series of articles about invokedynamic https://alex-ber.medium.com/explaining-invokedynamic-introduction-part-i-1079de618512. Below, I'm quoting the relevant parts from their.

MethodHandle can be thought as s more powerful alternative to Core Reflection API. MethodHandle is such an Object which stores the metadata about the method (constructor, field, or similar low-level operation), such as the name of the method signature of the method etc. One way took on it is a destination of the pointer to method (de-referenced method (constructor, field, or similar low-level operation)).

Java code can create a method handle that directly accesses any method, constructor, or field that is accessible to that code. This is done via a reflective, capability-based API called MethodHandles.Lookup For example, a static method handle can be obtained from Lookup.findStatic. There are also conversion methods from Core Reflection API objects, such as Lookup.unreflect.

It is important to understand 2 key difference from Core Reflection API and MethodHandle.

  • With MethodHandle access check is done only once in construction time, with Core Reflection API it is done on every call to invoke method (and Securty Manager is invoked each time, slowing down the performance).

  • Core Reflection API invoke method is regular method. In MethodHandle all invoke* variances are signature polymorphic methods.

Basically, access check means whether you can access method (constructor, field, or similar low-level operation). For example, if the method (constructor, field, or similar low-level operation) is private, you can’t normally invoke it (get value from the field).

As opposed to the Reflection API, the JVM can completely see-through MethodHandles and will try to optimize them, hence the better performance.

Note: With MethodHandle you can also generate implementation logic. See Dynamical hashCode implementation. Part V https://alex-ber.medium.com/explaining-invokedynamic-dynamical-hashcode-implementation-part-v-16eb318fcd47 for details.

Autres conseils

What you can do with MethodHandles is curry methods, change the types of parameters and change their order.

Method Handles can handle both methods and fields.

Another trick which MethodHandles do is use primitive direct (rather than via wrappers)

MethodHandles can be faster than using reflection as there is more direct support in the JVM e.g they can be inlined. It uses the new invokedynamic instruction.

java.lang.reflect.Method is relatively slow and expensive in terms of memory. Method handles are supposed to be a "lightweight" way of passing around pointers to functions that the JVM has a chance of optimising. As of JDK8 method handles aren't that well optimised, and lambdas are likely to be initially implemented in terms of classes (as inner classes are).

Think of MethodHandle as a modern, more flexible, more typesafe way of doing reflection.

It's currently in the early stages of its lifecycle - but over time has the potential to be optimized to become must faster than reflection - to the point that it can become as fast as a regular method call.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top