Invokedynamic 101

1 2 3 Page 3
Page 3 of 3
Classfile /C:/cpw/javaqa/article12/code/IDD/IDD.class
  Last modified 6-Dec-2014; size 390 bytes
  MD5 checksum ee1ec44a736cc0d446337023ec1a8ba6
public class IDD
  BootstrapMethods:
    0: #17 invokestatic IDDL.bootstrapDynamic:
              (Ljava/lang/invoke/MethodHandles$Lookup;
               Ljava/lang/String;Ljava/lang/invoke/MethodType;)
              Ljava/lang/invoke/CallSite;
      Method arguments:
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER

Constant pool:
   #1 = Utf8               IDD
   #2 = Class              #1             //  IDD
   #3 = Utf8               java/lang/Object
   #4 = Class              #3             //  java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = NameAndType        #5:#6          //  "<init>":()V
   #8 = Methodref          #4.#7          //  java/lang/Object."<init>":()V
   #9 = Utf8               main
  #10 = Utf8               ([Ljava/lang/String;)V
  #11 = Utf8               IDDL
  #12 = Class              #11            //  IDDL
  #13 = Utf8               bootstrapDynamic
  #14 = Utf8               (Ljava/lang/invoke/MethodHandles$Lookup;
                            Ljava/lang/String;
                            Ljava/lang/invoke/MethodType;)
                           Ljava/lang/invoke/CallSite;
  #15 = NameAndType        #13:#14        //  bootstrapDynamic:
                                          //     (Ljava/lang/invoke/MethodHandles$Lookup;
                                          //      Ljava/lang/String;
                                          //      Ljava/lang/invoke/MethodType;)
                                          //     Ljava/lang/invoke/CallSite;
  #16 = Methodref          #12.#15        //  IDDL.bootstrapDynamic:
                                          //     (Ljava/lang/invoke/MethodHandles$Lookup;
                                          //      Ljava/lang/String;
                                          //      Ljava/lang/invoke/MethodType;)
                                          //     Ljava/lang/invoke/CallSite;
  #17 = MethodHandle       #6:#16         //  invokestatic IDDL.bootstrapDynamic:
                                          //     (Ljava/lang/invoke/MethodHandles$Lookup;
                                          //      Ljava/lang/String;
                                          //      Ljava/lang/invoke/MethodType;)
                                          //     Ljava/lang/invoke/CallSite;
  #18 = Utf8               foo
  #19 = NameAndType        #18:#6         //  foo:()V
  #20 = InvokeDynamic      #0:#19         //  #0:foo:()V
  #21 = Utf8               Code
  #22 = Utf8               BootstrapMethods
{
  public IDD();
    flags: ACC_PUBLIC

    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: return        

  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=0, locals=1, args_size=1
         0: invokedynamic #20,  0             // InvokeDynamic #0:foo:()V
         5: return        
}

This output reveals a default constructor and a main() method. main() executes the invokedynamic followed by return JVM instructions.

invokedynamic is called with argument #20, which refers to the 20th entry in the constant pool. This entry provides a symbolic reference to a call site specifier in the form of an InvokeDynamic structure.

The InvokeDynamic structure presents a pair of values:

  • #0 is an index into the BootstrapMethods table, which provides linkage between the invokedynamic call site and the target method. Linkage is described by an index to a MethodHandle structure in the constant pool. In this case, the index is #17. The MethodHandle structure identifies a static bootstrapDynamic() method in an IDDL class.
  • #19 is an index to a NameAndType structure in the constant pool that identifies a fictitious void foo() method. This method is a placeholder for the method that gets called after the linkage is complete.

Compile Listing 5 (javac IDDL.java) and run IDD.class (java IDD). You should observe the following output, which reveals the result of invokedynamic working in partnership with java.lang.invoke:

Hello, World!

Invokedynamic and Java 8

Q: Does the Java 8 compiler emit invokedynamic instructions?

A: The Java 8 compiler emits invokedynamic instructions in lambda expression contexts. For example, consider Listing 7.

Listing 7. LD.java

public class LD // Lambda demo
{
   public static void main(String[] args)
   {
      Runnable r = () -> System.out.println("Hello");
      r.run();
   }
}

Listing 7 reveals a very simple lambda expression that equates to the java.lang.Runnable type. After creating this expression, main() invokes Runnable's run() method to run the lambda body.

Compile Listing 7 (javac LD.java) and run the resulting classfile (java LD). You should observe the following output:

Hello

Now that you know that the source code is correct and that the application runs successfully, run the javap tool with the -c option to view main()'s bytecode (javap -c LD.class). You should observe the following output, which reveals the presence of invokedynamic:

Compiled from "LD.java"
public class LD {
  public LD();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
    Code:
       0: invokedynamic #2,  0              // InvokeDynamic #0:run:()Ljava/lang/Runnable;
       5: astore_1      
       6: aload_1       
       7: invokeinterface #3,  1            // InterfaceMethod java/lang/Runnable.run:()V
      12: return        
}

If you would like to observe the constant pool along with the bootstrap methods table, include the -v option when executing javap.

What's next?

This post offers only a brief introduction to invokedynamic. To learn more about this useful instruction and its companion java.lang.invoke package, check out the following resources:

download
Get the source code for this post's applications. Created by Jeff Friesen for JavaWorld

The following software was used to develop the post's code:

  • 64-bit JDK 7u6
  • 64-bit JDK 8 (build 132)

The post's code was tested on the following platform(s):

  • JVM on 64-bit Windows 7 SP1
1 2 3 Page 3
Page 3 of 3