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指令。 - 如果需要具有易变变量语义的可变目标,因为对目标的更新必须立即可靠地由其他线程见证,可以使用 不稳定的呼叫站点。
- 否则,如果需要可变目标,则可以使用 可变调用站点。
一个不固定的呼叫站点可能是relinked通过改变它的目标。新目标必须与之前的目标具有相同的type。因此,尽管调用站点可以重新链接到一系列连续的目标,但它不能更改其类型。
以下是调用站点和引导方法的示例使用,它链接每个动态调用站点以打印其参数:
static void test() throws Throwable { // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION 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) { // ignore caller and name, but match the type: return new ConstantCallSite(printArgs.asType(type)); }
-
方法总结
修饰符和类型方法描述abstract MethodHandle生成等效于已链接到此调用站点的 invokedynamic 指令的方法句柄。abstract MethodHandle根据此调用站点的特定类定义的行为,返回调用站点的目标方法。abstract voidsetTarget(MethodHandle newTarget) 根据此调用站点的特定类定义的行为,更新此调用站点的目标方法。type()返回此调用站点目标的类型。
-
方法详情
-
type
返回此调用站点目标的类型。尽管目标可能会改变,但任何调用站点的类型都是永久性的,并且永远不会更改为不相等的类型。setTarget方法通过拒绝任何不具有先前目标类型的新目标来强制执行此不变量。- 返回:
- 当前目标的类型,也是任何未来目标的类型
-
getTarget
根据此调用站点的特定类定义的行为,返回调用站点的目标方法。CallSite的直接子类记录了此方法的类特定行为。- 返回:
- 调用站点的当前链接状态,其目标方法句柄
- 参见:
-
setTarget
根据此调用站点的特定类定义的行为,更新此调用站点的目标方法。CallSite的直接子类记录了此方法的类特定行为。新目标的类型必须是等于旧目标的类型。
- 参数:
newTarget- 新目标- 抛出:
NullPointerException- 如果提议的新目标为空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)- 返回:
- 始终调用此调用站点的当前目标的方法句柄
-