java.lang.Object
java.lang.invoke.CallSite
- 直接已知的子类:
-
ConstantCallSite
,MutableCallSite
,VolatileCallSite
public abstract sealed class CallSite extends Object permits ConstantCallSite, MutableCallSite, VolatileCallSite
一个
CallSite
是一个变量MethodHandle
的持有者,被称为它的target
。一个链接到CallSite
的invokedynamic
指令将所有调用委托给站点的当前目标。一个CallSite
可以与多个invokedynamic
指令关联,或者它可以是“自由浮动”的,不与任何关联。无论哪种情况,它都可以通过一个关联的方法句柄调用,称为它的动态调用器。
CallSite
是一个抽象密封类,不允许用户直接子类化。它有三个直接的、具体的非密封子类,可以被实例化或子类化。
- 如果不需要可变目标,可以通过常量调用站点永久绑定
invokedynamic
指令。 - 如果需要具有易失性变量语义的可变目标,因为目标的更新必须立即且可靠地被其他线程观察到,可以使用易失性调用站点。
- 否则,如果需要可变目标,可以使用可变调用站点。
非常量调用站点可以通过更改其目标来进行重新链接。新目标必须与先前目标具有相同的类型。因此,虽然调用站点可以重新链接到一系列连续的目标,但它不能改变其类型。
以下是调用站点和引导方法的示例用法,将每个动态调用站点链接到打印其参数:
static void test() throws Throwable { // 以下行是JVM指令的伪代码 InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14); } private static void printArgs(Object... args) { System.out.println(java.util.Arrays.deepToString(args)); } private static final MethodHandle printArgs; static { MethodHandles.Lookup lookup = MethodHandles.lookup(); Class thisClass = lookup.lookupClass(); // (who am I?) printArgs = lookup.findStatic(thisClass, "printArgs", MethodType.methodType(void.class, Object[].class)); } private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) { // 忽略调用者和名称,但匹配类型: return new ConstantCallSite(printArgs.asType(type)); }
-
Method Summary
Modifier and TypeMethodDescriptionabstract MethodHandle
生成等效于已链接到此调用站点的invokedynamic指令的方法句柄。abstract MethodHandle
根据此调用站点的特定类定义的行为,返回调用站点的目标方法。abstract void
setTarget
(MethodHandle newTarget) 根据此调用站点的特定类定义的行为,更新此调用站点的目标方法。type()
返回此调用站点目标的类型。
-
Method Details
-
type
返回此调用站点目标的类型。尽管目标可能会更改,但任何调用站点的类型都是永久的,永远不会更改为不相等的类型。setTarget
方法通过拒绝任何不具有先前目标类型的新目标来强制执行此不变性。- 返回:
- 当前目标的类型,也是任何未来目标的类型
-
getTarget
根据此调用站点的特定类定义的行为,返回调用站点的目标方法。CallSite
的直接子类记录了此方法的类特定行为。- 返回:
- 调用站点的当前链接状态,其目标方法句柄
- 参见:
-
setTarget
根据此调用站点的特定类定义的行为,更新此调用站点的目标方法。CallSite
的直接子类记录了此方法的类特定行为。新目标的类型必须等于旧目标的类型。
- 参数:
-
newTarget
- 新目标 - 抛出:
-
NullPointerException
- 如果建议的新目标为null -
WrongMethodTypeException
- 如果建议的新目标具有与先前目标不同的方法类型 - 参见:
-
dynamicInvoker
生成等效于已链接到此调用站点的invokedynamic指令的方法句柄。此方法等效于以下代码:
MethodHandle getTarget, invoker, result; getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class)); invoker = MethodHandles.exactInvoker(this.type()); result = MethodHandles.foldArguments(invoker, getTarget)
- 返回:
- 一个方法句柄,始终调用此调用站点的当前目标
-