invokedynamic是Java 7时引入的新的JVM指令。 通过invokedynamic可以在运行时再决定要调用哪个方法。 有了invokedynamic,可以更方便地在JVM上实现类似Ruby的动态语言。

下面的两段话非常好地概括了invokedynamic的机制。

Each instance of an invokedynamic instruction is called a dynamic call site. A dynamic call site is originally in an unlinked state, which means that there is no method specified for the call site to invoke. As previously mentioned, a dynamic call site is linked to a method by means of a bootstrap method. A dynamic call site’s bootstrap method is a method specified by the compiler for the dynamically-typed language that is called once by the JVM to link the site. The object returned from the bootstrap method permanently determines the call site’s behavior.

The invokedynamic instruction contains a constant pool index (in the same format as for the other invoke instructions). This constant pool index references a CONSTANT_InvokeDynamic entry. This entry specifies the bootstrap method (a CONSTANT_MethodHandle entry), the name of the dynamically linked method, and the argument types and return type of the call to the dynamically linked method.

invokedynamic指令出现的地方叫做“call site”(“调用点”)。 一开始call site处于“unlinked”状态,也就是还没有确定要调用哪个方法。 执行invokedynamic时,JVM会先去调用一个“bootstrap method”来确定要调用的方法。

invokedynamic指令的参数里包含了当前这条invokedynamic指令的“bootstrap method”信息(通过一个constant pool index“指向”bootstrap method)。

“bootstrap method”是普通的Java方法,有固定的参数类型和返回类型。 返回类型是CallSiteCallSite对象里有MethodHandleMethodHandle实际上就对应于一个方法)。 下面就是一个“bootstrap method”的声明,

public static CallSite mybsm(
    MethodHandles.Lookup callerClass, String dynMethodName, MethodType dynMethodType) {}

使用invokedynamic时,先定义好“bootstrap method”(可以多个invokedynamic指令共用一个“bootstrap method”,视情况而定)。 然后再构造相关的字节码,比如invokedynamic指令对应的字节码,constant pool相关的字节码等。 字节码可以通过ASM库来帮助构造,比如这个例子

invokedynamic除了用来在JVM上实现动态语言,还用来实现Java 8里的Lambda

更多详细信息见官网文档