Mig*_*boa 2 jvm invokedynamic java-8
Java 8引入了对第一类函数的支持,它允许将函数赋值给变量.在这种情况下,变量必须是函数类型,它由函数接口(只有一个抽象方法的接口)定义.
因此,考虑一个接口I和A具有以下定义的类的示例:
interface I{ int foo(); }
class A implements I{
public int foo(){return 7;}
public static int bar(){return 11;}
}
Run Code Online (Sandbox Code Playgroud)
我们可以分配给类型的变量I的实例A或方法参考该方法bar的A.两者都可以存储在类型的变量中I,例如:
I i1 = new A();
I i2 = A::bar;
Run Code Online (Sandbox Code Playgroud)
如果我们分析前面代码编译产生的字节码,我们将得到:
0: new #2 // class A
3: dup
4: invokespecial #3 // Method A."<init>":()V
7: astore_1
8: invokedynamic #4, 0 // InvokeDynamic #0:foo:()LI;
13: astore_2
Run Code Online (Sandbox Code Playgroud)
因为i1 = new A();这显然是相应的指令7: astore_1存储A与之兼容的实例I.但是,由于i2 = A::bar我们正在存储结果8: invokedynamic #4, 0.
那么,这意味着a的结果invokedynamic总是一个目标类型的实例,它是我们用方法引用分配的变量的类型?
每个invokedynamic字节码指的是常量池中对应的CONSTANT_InvokeDynamic_info结构.此结构包含一个方法描述符,用于派生参数的类型和该invokedynamic指令的返回值的类型.
在您的示例中,方法描述符是()LI;在源到字节码转换期间计算的.
8: invokedynamic #4, 0 // InvokeDynamic #0:foo:()LI;
^^^^^
Run Code Online (Sandbox Code Playgroud)
这意味着此特定字节码不需要参数,并始终生成类型的结果I.