YON Blog

invokedynamic 和 Lambda

invokeydynamic 的执行机制就不说了,这个可以直接看 深入理解 Java 虚拟机 这书。关键的一点是,invokedynamic 和 Lambda 运行时的真正执行没有关系,换句话说就是,你 Lambda 里逻辑的执行并不是通过 invokedynamic 调用的。那 invokedynamic 是什么作用呢?

我们使用 Lambda 的地方一般是某个函数需要传入一个接口的实例,invokedynamic 的作用就是创建这个实例。为什么 Java 要通过这个方式来支持呢?回答这个问题我们可以先考虑下,如果不通过这个方式来支持,还有什么方式来支持呢?一个很符合直觉的做法就是,Java 编译器直接在编译阶段把 Lambda 表达式翻译成和使用匿名类创建对象一样的字节码,这里的关键是在编译阶段就做这个操作。这样做的坏处是对于 Lambda 的支持是固化的,以后即使有更好的方式去支持 Lambda,已经编译好的 class 文件都只能以匿名类的方式去运行。

如果看过 java.lang.invoke.LambdaMetafactory#metafactory 的代码你会知道现在 Java 对 Lambda 的实现是通过在运行时用 ASM 技术动态创建匿名类来实现的,似乎无论是编译时还是运行时都只能通过匿名类来支持 Lambda。其实不是的,我们还可以通过 MethodHandle 的方式来支持,可以看下 java.lang.invoke.MethodHandleProxies#asInterfaceInstance 这个方法。

[1] Translation of Lambda Expressions

[2] Java 8的Lambda表达式为什么要基于invokedynamic? - RednaxelaFX的回答