

详情见 Class LambdaMetafactory 官方文档,java.lang.invoke.LambdaMetafactory#metafactory 的实现。
public static CallSite metafactory(MethodHandles.Lookup caller,
String invokedName,
MethodType invokedType,
MethodType samMethodType,
MethodHandle implMethod,
MethodType instantiatedMethodType)
throws LambdaConversionException {
AbstractValidatingLambdaMetafactory mf;
mf = new InnerClassLambdaMetafactory(caller, invokedType,
invokedName, samMethodType,
implMethod, instantiatedMethodType,
false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
mf.validateMetafactoryArgs();
return mf.buildCallSite();
}
其主要的概念有如下几个:
- invokedynamic 字节码指令:运行时 JVM 第一次到某个地方的这个指令的时候会进行 linkage,会调用用户指定的 Bootstrap Method 来决定要执行什么方法,之后便不需要这个步骤。
- Bootstrap Method: 用户可以自己编写的方法,最终需要返回一个 CallSite 对象。
- CallSite: 保存 MethodHandle 的容器,里面有一个 target MethodHandle。
MethodHandle: 真正要执行的方法的指针。

测试一下 Lambda 函数生成的字节码,为了方便起见,java 代码改成如下:
public class LambdaMain {
public static void main(String[] args) {
new Thread(() -> System.out.println("1")).start();
}
}
先编译成 class 文件,之后再反汇编 javap -c -p LambdaMain 看下输出:
Compiled from "LambdaMain.java"
public class test.jdk.LambdaMain {
public test.jdk.LambdaMain();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/lang/Thread
3: dup
4: invokedynamic #3, 0 // InvokeDynamic #0:run:()Ljava/lang/Runnable;
9: invokespecial #4 // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V
12: invokevirtual #5 // Method java/lang/Thread.start:()V
15: return
private static void lambda$main$0();
Code:
0: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #7 // String 1
5: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
}
可以看到 Thread 里的 Runnable 实现是通过 invokedynamic 调用的。详细情况 JVM 虚拟机规范,等有时间再补充吧~~~
总结
- Lambda 表达式在 Java 中最终编译成
私有的静态函数,JDK 最终使用 invokedynamic 字节码指令调用。
文章均来自互联网如有不妥请联系作者删除QQ:314111741 地址:http://www.mqs.net/post/12351.html
添加新评论