![](/img/trans.png)
[英]Why Java-8 lambda need invokeDynamic byteCode to invoke an interface method
[英]Java bytecode, java Supplier and invokedynamic argument
我有这个课,我编译它。
package org.test;
import java.util.function.Supplier;
public class Test {
static String get() { return "!!"; }
public static void main(String[] args) {
Supplier<String> sup = Test::get;
System.out.println(sup.get());
}
}
然后,试着查看它的字节码,我得到以下public static void main
函数的开头:
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: invokedynamic #3, 0 // InvokeDynamic #0:get:()Ljava/util/function/Supplier;
5: astore_1
6: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
在这里我们可以看到invokedynamic调用,如果我理解正确的话,它会创建一个Supplier接口的匿名实例。 传递给invokedynamic有两个参数,一个是#3。 第二个参数是0.所以,我的第一个问题是:0代表什么?
在常量池#3中代表#3 = InvokeDynamic #0:#27 // #0:get:()Ljava/util/function/Supplier;
。 在常量池中引用#27,但没有引用#0。 我的第二个问题是:#0代表什么?
#0
(您可以在invokedynamic旁边的注释中看到)实际上是BootstrapMethods
表中的索引。 所以第一个问题, 0
实际上是指#0
。 而这又是BootstrapMethods表的索引。 它提供了invokedynamic
调用源和目标方法之间的链接。
如果您使用javap -c -v FileName
反编译,您将看到整个常量池。 (我假设你做了什么?)。 在这里你应该找到对#X MethodHandle #y:#z IDDL.bootstrapDynamic
的引用#X MethodHandle #y:#z IDDL.bootstrapDynamic
。 这就是BootstrapMethods表链接的地方。 #0
链接到的句柄最终应解析为static bootstrapDynamic()
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.