Skip navigation links
Java™ Platform
Standard Ed. 8

Package java.lang.invoke

java.lang.invoke软件包包含由Java核心类库和虚拟机直接提供的动态语言支持。

See: 描述

Package java.lang.invoke Description

java.lang.invoke包包含由Java核心类库和虚拟机直接提供的动态语言支持。

如Java虚拟机规范中所述,此包中的某些类型与虚拟机中的动态语言支持具有特殊关系:

相关Java虚拟机更改摘要

以下低级信息总结了Java虚拟机规范的相关部分。 有关详细信息,请参阅该规范的当前版本。 invokedynamic指令的invokedynamic发生都称为动态呼叫站点

invokedynamic说明

动态呼叫站点最初处于未连接状态。 在这种状态下,呼叫站点没有调用的目标方法。

在JVM可以执行动态呼叫站点( invokedynamic指令)之前,呼叫站点必须首先被链接 链接是通过调用引用方法来实现的,该方法被赋予呼叫站点的静态信息内容,并且必须产生给出呼叫站点行为的method handle

每个invokedynamic指令静态地将其自己的引导方法指定为常量池引用。 常量池引用还指定了调用站点的名称和类型描述符,就像invokevirtual和其他调用指令一样。

链接起始于解决引导方法的常量池条目,并为动态调用站点的类型描述符解析MethodType对象。 该解析过程可能会触发类加载。 如果类无法加载,它可能会抛出错误。 该错误成为动态呼叫站点执行的异常终止。 Linkage不会触发类初始化。

至少三个值调用引导方法:

调用就像MethodHandle.invoke一样 返回的结果必须是CallSite (或子类)。 调用站点的目标类型必须与从动态调用站点的类型描述符派生的类型完全相同,并传递给引导方法。 然后呼叫站点将永久链接到动态呼叫站点。

如JVM规范记录,从动态调用网站的链接而产生的所有故障是由报道BootstrapMethodError ,这是抛出动态调用点执行的异常终止。 如果发生这种情况,将会对所有后续尝试执行动态调用站点抛出相同的错误。

联动时机

动态呼叫站点在其第一次执行之前已链接。 引导程序调用实现链接发生在正在尝试执行第一次的线程中。

如果有多个这样的线程,引导方法可能会同时在多个线程中调用。 因此,访问全局应用程序数据的引导方法必须采取针对竞争条件的通常预防措施。 无论如何,每个invokedynamic指令都将被取消链接或链接到唯一的CallSite对象。

在需要具有单独可变行为的动态调用站点的应用程序中,它们的引导方法应该产生不同的CallSite对象,每个连接请求一个。 或者,应用程序可以将单个CallSite对象链接到多个invokedynamic指令,在这种情况下,对于invokedynamic指令,对目标方法的更改将变得可见。

如果多个线程同时执行单个动态调用站点的引导方法,则JVM必须选择一个CallSite对象并将其明显地安装到所有线程。 允许任何其他引导方法调用完成,但其结果将被忽略,并且其动态调用站点调用继续处理原始选择的目标对象。

讨论:这些规则不能使JVM重复动态调用站点,也不会发出“无效”引导方法调用。 每个动态调用站点在其第一次调用之前,最多只能从一个链接转换为一个链接。 没有办法撤销完成的引导方法调用的效果。

引导方式的类型

只要每个自举方法可通过正确地调用MethodHandle.invoke ,其详细的类型是任意的。 例如,第一个参数可以是Object而不是MethodHandles.Lookup ,返回类型也可以是Object而不是CallSite (请注意,堆栈参数的类型和数量限制了适当类型的引导方法到适当类型的静态方法和CallSite子类的CallSite函数。)

如果给定的invokedynamic指令没有指定静态参数,则将在三个参数上调用指令的引导方法,传达指令的调用者类,名称和方法类型。 如果invokedynamic指令指定一个或多个静态参数,则这些值将作为附加参数传递给方法句柄。 (请注意,因为任何方法都有255个参数的限制,因此可以提供最多251个额外的参数,因为引导方法处理本身,并且前三个参数也必须被堆叠。)引导方法将被调用,就像MethodHandle.invokeinvokeWithArguments (没有办法说出差异。)

对于普通参数转换规则MethodHandle.invoke适用于所有堆叠的论点。 例如,如果推送的值是原始类型,则可以通过拳击转换将其转换为引用。 如果引导方法是一个变量arity方法(它的修饰符位设置为0x0080 ),那么这里指定的一些或全部参数可能被收集到一个尾随的数组参数中。 (这不是一个特殊的规则,而是CONSTANT_MethodHandle常量之间的CONSTANT_MethodHandle的有用后果,变量arity方法的修饰符位和asVarargsCollector转换。)

鉴于这些规则,这里,给出不同数量的法律引导方法声明的例子N的额外的参数。 第一行(标记为* )将适用于任何数量的额外参数。

N sample bootstrap method * CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args) * CallSite bootstrap(Object... args) * CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs) 0 CallSite bootstrap(Lookup caller, String name, MethodType type) 0 CallSite bootstrap(Lookup caller, Object... nameAndType) 1 CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg) 2 CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args) 2 CallSite bootstrap(Lookup caller, String name, MethodType type, String... args) 2 CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)
最后一个例子假设额外的参数是类型CONSTANT_StringCONSTANT_Integer ,分别。 第二个到最后一个例子假设所有额外的参数都是类型CONSTANT_String 其他示例适用于所有类型的额外参数。

如上所述,引导方法的实际方法类型可以变化。 例如,第四个参数可以是MethodHandle ,如果是CONSTANT_InvokeDynamic条目中对应的常量的类型。 在这种情况下, MethodHandle.invoke呼叫将通过额外的方法作为处理常数Object ,但类型匹配机械MethodHandle.invoke将施放返回参考MethodHandle调用的自举方法之前。 (如果传递一个字符串常量,那么由生成的代码不好,那么该转换将失败,导致一个BootstrapMethodError ))

请注意,作为上述规则的结果,引导方法可以接受原始参数,如果它可以由常量池条目表示。 然而,类型的参数booleanbyteshort ,或char不能自举方法来创建的,因为这样的常量不能直接在常量池中表示,并且自举方法的调用将不执行必要的基本收缩转换。

额外的引导方法参数旨在允许语言实现者安全和紧凑地编码元数据。 原则上,名称和额外的参数是冗余的,因为每个调用站点都可以被赋予自己独特的引导方法。 这种做法很可能会产生大型的类文件和常量池。

从以下版本开始:
1.7
Skip navigation links
Java™ Platform
Standard Ed. 8