invokedynamic, a new bytecode instruction on the JVM for method invocation. The
invokedynamicinstruction allows dynamic linkage between a call site and the receiver of the call. That means you can link the class that is performing a method call to the class (and method) that is receiving the call at run-time. All the other JVM bytecode instructions for method invocation, like
invokevirtual, hard-wire the target type information into your compilation, i.e. into your class file. Let's look at an example.
The bytecode snippet above shows an
invokevirtualmethod call of
java.lang.String -> length()in line 20. It refers to item 65 in the contsant pool table which is a
MethodRefentry (see line 6). Items 42 and 66 in the constant pool table refer to the class and the method descriptor entries. As you can see, the target type and method of the
invokevirtualcall is completely resolved and hard-wired into the bytecode. Now, let's return to
It is important to notice that it is not possible to compile Java code into bytecode that contains an
invokedynamicinstruction. Java is statically typed. That means that Java performs type checking at compile time. Therefore, in Java, it is possible (and wanted!) to hard-wire all type information of method call receivers into the callers class file. The caller knows the type name of the call target, as demonstrated in our example above. The use of
invokedynamic- on the other hand - enables the JVM to resolve exactly that type information at run-time. This is only required (and wanted!) for dynamic languages, such as JRuby or Rhino.
Now, suppose you want to implement a new language on the JVM that is dynamically typed. I am not suggesting you should invent *another* language on the JVM, but *suppose* you would, and *suppose* your new language should be dynamically typed. That would mean, in your new language, the linking between a caller and a receiver of a method call is performed at run-time. Since Java 7 this is possible on the bytecode level using the
Because I cannot create an
invokedynamicinstruction using a Java compiler, I will create a class file that contains
invokedynamicmyself. Once this class file is created I will run that class file's
mainmethod using an ordinary
javalauncher. How can you create a class file without a compiler? This is possible by using bytecode manipulation frameworks like ASM or Javassist.
The following code snippet shows the
SimpleDynamicInvokerGeneratorthat can generate a class file
SimpleDynamicInvoker.classwhich contains an invokedynamic instruction.
I am using ASM here, an all purpose Java bytecode manipulation and analysis framework, to do the job of creating a correct class file format. In line 30 the
invokedynamicinstruction. Generating a class that does an
invokedynamiccall is only half of the story. You also need some code that links the dynamic call site to the actual target, this is the real purpose of
invokedynamic. Here is an example.
The bootstrap method in line 9-14 selects the actual target of the dynamic call. In our case the target is the
sayHello()method. To learn how the bootstrap method is linked to the
invokedynamicinstruction we need to dive into the bytecode of
SimpleDynamicInvokerthat we've generated with
In line 49 you can see the
invokedynamicinstruction. The logical name of the dynamic method is
runCalculation, this is a fictitious name. You can use any name that makes sense, also names like "+" are allowed. The instruction refers to item 20 in the contant pool table (see line 33). This in turn refers to index 0 in the
BootstrapMethodsattribute (see line 8). There you can see the link to the
SimpleDynamicLinkageExample.bootstrapDynamicmethod that links the
invokedynamicinstruction to the call target.
Now if you call the
javalauncher, then the
invokedynamiccall is executed.
The following sequence diagram illustrates what's happening when the
SimpleDynamicInvokeris called using the
The first call of
invokedynamicissues a call to the
bootstrapDynamicmethod. This method does the dynamic linkage between the calling class (
SimpleDynamicInvoker) and the receiving class (
SimpleDynamicLinkageExample). The bootstrap method returns a
MethodHandlethat targets the receiving class. This method handle is cached for repetitive invocations of the
That's all in terms of
invokedynamic. I have some more sophisticated examples published here in my Git repo. I hope you've enjoyed reading this - in times of shortage!