- java.lang.Object
-
- java.lang.invoke.SwitchPoint
-
public class SwitchPoint extends Object
A
SwitchPoint
是可以将状态转换发布到其他线程的对象。 切换点最初处于有效状态,但可随时更改为无效状态。 无效无法撤销。 切换点可以将守卫的一对方法句柄组合成守卫的委托者 。 守卫的委托者是一个方法句柄,它将一个旧的方法句柄委托。 切换点的状态确定两者中的哪一个获得授权。单个切换点可用于控制任意数量的方法句柄。 (间接地,它可以控制任何数量的呼叫站点)。这是通过使用单个切换点作为工厂来完成的,将任意数量的守卫方法句柄对组合成守卫的委托者。
当一个守卫的委托者是从一个守卫的对创建的时候,该对被包裹在一个新的方法句柄
M
,它与创建它的切换点永久关联。 每一对由目标T
和后退F
。 当切换点有效时,调用M
被委派给T
。 无效后,调用将被委派给F
。无效是全局和立即的,就像在每次调用
M
时,切换点包含一个易失性布尔变量M
。 无效也是永久的,这意味着切换点只能改变一次状态。 切换点将无效后始终委托给F
。 那时guardWithTest
可能会忽略T
并返回F
。下面是一个切换点的例子:
MethodHandle MH_strcat = MethodHandles.lookup() .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class)); SwitchPoint spt = new SwitchPoint(); assert(!spt.hasBeenInvalidated()); // the following steps may be repeated to re-use the same switch point: MethodHandle worker1 = MH_strcat; MethodHandle worker2 = MethodHandles.permuteArguments(MH_strcat, MH_strcat.type(), 1, 0); MethodHandle worker = spt.guardWithTest(worker1, worker2); assertEquals("method", (String) worker.invokeExact("met", "hod")); SwitchPoint.invalidateAll(new SwitchPoint[]{ spt }); assert(spt.hasBeenInvalidated()); assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
讨论:切换点在没有子类化的情况下是有用的。 他们也可能被分类。 这可能是有用的,以便将应用程序特定的无效逻辑与切换点相关联。 请注意,切换点与其生成和使用的方法句柄之间没有永久关联。 垃圾收集器可以独立于开关点本身的寿命,收集切换点产生或消耗的方法手柄。
实现注意:切换点的行为就像在
MutableCallSite
之上实现一样 ,大致如下:public class SwitchPoint { private static final MethodHandle K_true = MethodHandles.constant(boolean.class, true), K_false = MethodHandles.constant(boolean.class, false); private final MutableCallSite mcs; private final MethodHandle mcsInvoker; public SwitchPoint() { this.mcs = new MutableCallSite(K_true); this.mcsInvoker = mcs.dynamicInvoker(); } public MethodHandle guardWithTest( MethodHandle target, MethodHandle fallback) { // Note: mcsInvoker is of type ()boolean. // Target and fallback may take any arguments, but must have the same type. return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback); } public static void invalidateAll(SwitchPoint[] spts) { List<MutableCallSite> mcss = new ArrayList<>(); for (SwitchPoint spt : spts) mcss.add(spt.mcs); for (MutableCallSite mcs : mcss) mcs.setTarget(K_false); MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0])); } }
- 从以下版本开始:
- 1.7
-
-
构造方法摘要
构造方法 Constructor 描述 SwitchPoint()
创建一个新的切换点。
-
方法摘要
所有方法 静态方法 接口方法 具体的方法 Modifier and Type 方法 描述 MethodHandle
guardWithTest(MethodHandle target, MethodHandle fallback)
返回一个方法句柄,它始终将它们委托给目标或后备。boolean
hasBeenInvalidated()
确定此切换点是否已被无效。static void
invalidateAll(SwitchPoint[] switchPoints)
将所有给定的切换点设置为无效状态。
-
-
-
方法详细信息
-
hasBeenInvalidated
public boolean hasBeenInvalidated()
确定此切换点是否已被无效。讨论:由于无效的单向性质,一旦
hasBeenInvalidated
开关点开始返回true,hasBeenInvalidated
会一直这样做。 另一方面,由于另一个线程的请求,其他线程可见的有效切换点可能在任何时候无效。由于无效是一个全局和立即的操作,所以在有效的切换点上执行此查询必须与可能导致无效的任何其他线程进行内部排序。 因此,该查询可能是昂贵的。 建立一个查询交换点
s
的无效状态的布尔值方法句柄的建议方法是调用s.guardWithTest
的constant
真假方法句柄。- 结果
- 如果此切换点已失效,则为true
-
guardWithTest
public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback)
返回一个方法句柄,它始终将它们委托给目标或后备。 只要切换点有效,方法句柄将正确地委派给目标。 之后,它将永久地委托回退。目标和后备必须是完全相同的方法类型,结果组合方法句柄也将是这种类型。
- 参数
-
target
- 切换点选择的方法句柄,只要它有效 -
fallback
- 切换点无效后选择的方法句柄 - 结果
- 总是调用目标或后备的组合方法句柄
- 异常
-
NullPointerException
- 如果任一参数为空 -
IllegalArgumentException
- 如果两种方法类型不匹配 - 另请参见:
-
MethodHandles.guardWithTest(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle)
-
invalidateAll
public static void invalidateAll(SwitchPoint[] switchPoints)
将所有给定的切换点设置为无效状态。 执行此呼叫后,任何线程都不会发现任何切换点处于有效状态。这个操作可能是昂贵的,应该谨慎使用。 如果可能,应对缓冲器进行缓冲,以便对交换点集合进行批处理。
如果
switchPoints
包含一个空元素,则会产生一个NullPointerException
。 在这种情况下,方法返回异常之前,可能会处理数组中的一些非空元素。 哪些元素(如果有的话)是依赖于实现的。讨论:出于性能原因,
invalidateAll
不是单个切换点上的虚拟方法,而是适用于一组切换点。 一些实现可能产生用于处理一个或多个无效操作的大的固定开销成本,但是对于每个额外的无效,都需要较小的增量成本。 在任何情况下,该操作可能是昂贵的,因为其他线程可能必须以某种方式中断,以便使它们注意更新的切换点状态。 然而,可以观察到,使多个切换点无效的单个呼叫与多个呼叫具有相同的形式效果,每个呼叫仅在一个切换点上。实现注意:
SwitchPoint
简单实现可能会使用私有的MutableCallSite
来发布切换点的状态。 在这种实现中,invalidateAll
方法可以简单地更改呼叫站点的目标,并发出一个呼叫到所有私人呼叫站点的synchronize 。- 参数
-
switchPoints
- 要同步的呼叫站点数组 - 异常
-
NullPointerException
- if theswitchPoints
array reference is null or the array contains a null
-
-