JAVA lambda实现原理(invokedynamic)

11月 24, 2021 |

源码和字节码

源码

Runnable r = () -> System.out.println("run");
r.run();

字节码如下

0: invokedynamic #2, 0 // InvokeDynamic #0:run:()L...Runnable;
...
7: invokeinterface #4, 1 // InterfaceMethod …Runnable.run:()V
BootstrapMethods:
0: #29 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;
Ljava/lang/String;Ljava/lang/invoke/MethodType;
Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;
Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
Method arguments:
#30 ()V
#31 invokestatic TestDynamicInvoke.lambda$main$0:()V
#30 ()V

字节码解析如下图

启用-Djdk.internal.lambda.dumpProxyClasses=D:\var\log 调试开关产生的内部类如下:

流程总结

当jvm遇到invokedynamic指令,根据#2索引查找BootstrapMethods属性定位到对应的启动方法,java8启动方法为LambdaMetafactory.metafactory,该方法执行的过程中会产生内部类来适配我们期望的Runnable接口,然后使用MethodHandle对象来引用我们产生的适配类的run方法,最后包装成CallSite返回,

MethodHandle是java1.8新加的,这套方法的调用机制是基于MethodType(使用参数+返回值来描述方法的签名),方法类型+方法名在一个类中唯一确定一个方法。比起反射MethodHandle便于实例方法和函数对象之间的转换

参考文档:

2015-Indy_Deep_Dive.pdf

Posted in: IT人生, java基础

Comments are closed.