Module java.base
Package java.lang.invoke

Class CallSite

java.lang.Object
java.lang.invoke.CallSite
直接已知的子类:
ConstantCallSite, MutableCallSite, VolatileCallSite

public abstract sealed class CallSite extends Object permits ConstantCallSite, MutableCallSite, VolatileCallSite
一个CallSite是一个变量MethodHandle的持有者,被称为它的target。一个链接到CallSiteinvokedynamic指令将所有调用委托给站点的当前目标。一个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));
}
密封类层次结构图:
CallSite的密封类层次结构图CallSite的密封类层次结构图
自Java版本:
1.7