Search code examples
jvmjava-8invokedynamic

How is stored the result of the invokedynamic?


Java 8 introduces support for first-class functions, which allows assigning functions to variables. In this case the variables must be of a function type, which is defined by a functional interface (an interface with just one abstract method).

So, considering an example of an interface I and a class A with the following definition:

interface I{ int foo(); }
class A implements I{ 
  public int foo(){return 7;} 
  public static int bar(){return 11;}
}

We can assign to a variable of type I an instance of A or a method reference to the method bar of A. Both can be store on variables of type I, such as:

I i1 = new A(); 
I i2 = A::bar;

If we analyze the bytecodes resulting from the compilation of the previous code we will get:

0: new           #2                  // class A
3: dup
4: invokespecial #3                  // Method A."<init>":()V
7: astore_1
8: invokedynamic #4,  0              // InvokeDynamic #0:foo:()LI;
13: astore_2

For i1 = new A(); that is clearly that the corresponding instruction 7: astore_1 is storing an instance of A that is compatible with I. But, as a result of the i2 = A::bar we are storing the result of the 8: invokedynamic #4, 0.

So, that means that the result of an invokedynamic is always an instance of the target type, which is the type of the variable that we are assigning with a method reference?


Solution

  • Each invokedynamic bytecode refers to a corresponding CONSTANT_InvokeDynamic_info structure in the constant pool. This structure contains a Method Descriptor that is used to derive the types of the arguments and the type of return value for this invokedynamic instruction.

    In your example the method descriptor is ()LI; computed during source-to-bytecode translation.

    8: invokedynamic #4,  0              // InvokeDynamic #0:foo:()LI;
                                                                 ^^^^^
    

    It means that this particular bytecode expects no arguments and always produces the result of type I.