什么是CONSTANT_MethodHandle、CONSTANT_MethodType和CONSTANT_InvokeDynamic?

4
我在研究Java字节码如何工作,开始在维基百科上查看。在专注于.class文件的页面上,它提到了11种常量类型出现在常量池中。然而,在Java虚拟机规范(JVMS)中,它提到了另外3种:
  • CONSTANT_MethodHandle
  • CONSTANT_MethodType
  • CONSTANT_InvokeDynamic
维基百科页面上提到的这11种似乎很容易理解,我理解它们的目的和用途。然而,我对JVMS中描述的3个额外的常量感到困惑。它们是什么,以及它们的用途是什么?
2个回答

3
请查看Java®虚拟机规范第4章 类文件格式
CONSTANT_MethodHandle_info结构用于表示方法句柄:
CONSTANT_MethodHandle_info {
    u1 tag;
    u1 reference_kind;
    u2 reference_index;
}

CONSTANT_MethodType_info结构用于表示方法类型:

CONSTANT_MethodType_info {
    u1 tag;
    u2 descriptor_index;
}

CONSTANT_InvokeDynamic_info 结构体被 invokedynamic 指令 (§invokedynamic) 使用,用于指定引导方法、动态调用名称、调用的参数和返回类型,以及可选的一系列称为静态参数的附加常量,这些参数将传递给引导方法。
CONSTANT_InvokeDynamic_info {
    u1 tag;
    u2 bootstrap_method_attr_index;
    u2 name_and_type_index;
}

更多信息请参见方法句柄和invokedynamicClass MethodHandle


对,我在问题中提供了链接。我想知道那些代码的含义,并且想知道它们如何转换为高级Java语言。 - Steven
请参阅方法句柄和invokedynamic - DavidPostill
啊,好的。你能编辑一下你的答案,这样我就可以接受它了吗? - Steven
从Java 7开始,在高级Java中它不会转换成任何东西,因为Java从不使用invokedynamic。类文件格式中的并非所有内容都一定被Java使用。在Java 8中,可以通过invokedynamic来实现lambda表达式,尽管我还没有检查编译器是否真正这样做。 - Antimony

3
MethodHandle基本上是对可执行操作的“句柄”。它可以是方法调用,甚至是变量赋值。MethodType是用于调用MethodHandle的调用签名。换句话说,它描述了参数和返回值。MethodHandle可能能够处理使用不同类型签名进行调用的情况。
要了解更多信息,请查看java.lang.invoke.MethodHandle和java.lang.invoke.MethodType。这些是在Java 7中引入的。当字节码使用LDC将MethodHandle_info或MethodType_info常量加载到堆栈上时,JVM将分别创建MethodHandle或MethodType类实例。
invokedynamic字节码指令将调用MethodHandle。引导方法将在第一次调用时确定它将调用哪个MethodHandle。这创建了一个可以在运行时更改其调用目标的invoke指令。这允许动态代码,无需在目标代码的某些方面发生更改时重新编译。这在Java 8中用于提供对lambda表达式的支持。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接