Question

As far as I can tell, with the introduction of MethodHandle in Java 7 came the introduction of compiler-generated method overloads.

The javadoc for MethodHandle states (I've trimmed the examples):

Here are some examples of usage:

Object x, y; String s; int i;
mh = ...
// (Ljava/lang/String;CC)Ljava/lang/String;
// (String, char, char) -> String
s = (String) mh.invokeExact("daddy",'d','n');

// (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
// (Object, Object, Object) -> Object
x = mh.invokeExact((Object)1, (Object)2, (Object)3);

// (Ljava/util/List;)I
// (List) -> int
i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));

// (Ljava/io/PrintStream;Ljava/lang/String;)V
// (PrintStream, String) -> void
mh.invokeExact(System.out, "Hello, world.");

Each of the above calls generates a single invokevirtual instruction with the name invoke and the type descriptors indicated in the comments. The argument types are taken directly from the actual arguments, while the return type is taken from the cast immediately applied to the call. This cast may be to a primitive. If it is missing, the type defaults to Object if the call occurs in a context which uses the return value. If the call occurs as a statement, a cast is impossible, and there is no return type; the call is void.

In effect, invokeExact and friends behave as if there is an overload for every possible combination of paramaters and return type.

I've heard that MethodHandles are preparing for features in Java 8 like lambdas. (I know they are already useful for scripting languages.)

[/introduction]

So, are there more of these compiler-generated overloads hiding around in Java? Are there hints there will be more of them in the future (say, with extension methods)? Why is it necessary in the first place? Merely speed? How does it help lambdas out (I thought lambdas would compile to an anonymous inner class)?

In short, what's the rationale; why are they (generated overloads) useful now and in the future?

UPDATE: What I call compiler-generated overloads here, the Oracle guys call signature polymophic.

Was it helpful?

Solution

I just came across an Hotspot internals wiki on MethodHandles and invokedynamic

It makes a few interesting points that answer these questions (and a few more).

  • What is called compiler-generated overloads in the question, the java guys call signature polymorphic.
  • MethodHandle.invokeExact and friends are unique, being the only signature polymorphic methods.
  • On the HotSpot VM, the invokevirtual bytecode for MethodHandle.invoke* is secretly converted to an invokehandle instruction.
    • invokehandle is like invokedynamic; a few internals are different, and where each invokedynamic instruction must point to it's own Constant Pool Cache Entry (CPCE), invokehandles can share CPCEs.
  • invokedynamic uses the non-public MethodHandle.invokeBasic on the HotSpot VM
    • MethodHandle.invokeBasic is like invokeExact but more loose; for one it does not check the types of at the call-site with those of the callee.
  • Hot method handles (including invokedynamic) can be JIT-compiled

Additionally, lambda expressions will be implemented via invokedynamic. (Got that from Edwin Dalorzo's answer.) This means lambda expressions

  • will indirectly use MethodHandle.invokeBasic on the HotSpot VM (see above), and
  • are eligible to be JIT-compiled

OTHER TIPS

These two links may not answer all your questions, but they might be a good starting point:

This is reference material comming from the expert group currently working in the JDK 8: Project Lambda. With luck you can find some explanations there, above all about your missconception of lambda expressions as inner classes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top