Java Virtual Machine Support for Non-Java Languages
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_InvokeDynamicentry. This entry specifies the bootstrap method (aCONSTANT_MethodHandleentry), 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方法,有固定的参数类型和返回类型。
返回类型是CallSite(CallSite对象里有MethodHandle,MethodHandle实际上就对应于一个方法)。
下面就是一个“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。
更多详细信息见官网文档。