public class MutableCallSite extends CallSite
MutableCallSite
是一个目标变量的行为像一个普通的领域
CallSite
。一个
invokedynamic
指令链接到一个
MutableCallSite
代表站点的当前目标的所有电话。一个可变呼叫现场
dynamic invoker也代表每次调用站点的当前目标。
这是一个可变的电话网站引入状态变量为方法处理链为例。
MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class)); MethodHandle MH_name = name.dynamicInvoker(); MethodType MT_str1 = MethodType.methodType(String.class); MethodHandle MH_upcase = MethodHandles.lookup() .findVirtual(String.class, "toUpperCase", MT_str1); MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase); name.setTarget(MethodHandles.constant(String.class, "Rocky")); assertEquals("ROCKY", (String) worker1.invokeExact()); name.setTarget(MethodHandles.constant(String.class, "Fred")); assertEquals("FRED", (String) worker1.invokeExact()); // (mutation can be continued indefinitely)
同一个呼叫站点可以在几个地方同时使用。
MethodType MT_str2 = MethodType.methodType(String.class, String.class); MethodHandle MH_cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); MethodHandle MH_dear = MethodHandles.insertArguments(MH_cat, 1, ", dear?"); MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear); assertEquals("Fred, dear?", (String) worker2.invokeExact()); name.setTarget(MethodHandles.constant(String.class, "Wilma")); assertEquals("WILMA", (String) worker1.invokeExact()); assertEquals("Wilma, dear?", (String) worker2.invokeExact());
目标值的非同步:写个可变调用网站的目标不强迫其他线程意识到更新后的值。相对于更新的调用站点不执行合适的同步操作的线程可以缓存旧的目标值,并无限期地延迟它们的新目标值的使用。(这是一个普通的java内存模型应用于目标领域。)
的syncAll
操作来迫使线程来接受一个新的目标值提供,即使没有其他同步。
目标值,将经常更新,请考虑使用volatile call site相反。
Constructor and Description |
---|
MutableCallSite(MethodHandle target)
用初始目标方法处理创建一个调用站点对象。
|
MutableCallSite(MethodType type)
用给定的方法类型创建一个空白调用站点对象。
|
Modifier and Type | Method and Description |
---|---|
MethodHandle |
dynamicInvoker()
生产法处理相当于一个invokedynamic指令已与该调用站点。
|
MethodHandle |
getTarget()
返回调用点目标的方法,它的行为就像一个正常的领域
MutableCallSite 。
|
void |
setTarget(MethodHandle newTarget)
更新此调用站点的目标方法,作为一个正常变量。
|
static void |
syncAll(MutableCallSite[] sites)
在给定的数组中的每个调用站点上执行同步操作,强制所有其他线程丢弃先前从任何调用站点的目标加载的缓存值。
|
public MutableCallSite(MethodType type)
IllegalStateException
方法处理。
调用站点的类型永久设置为给定类型。
在这之前CallSite
对象从一个方法返回,或者调用一些其他的方式,它通常是提供一个更有用的目标的方法,通过调用setTarget
。
type
,这叫现场会有方法的类型
NullPointerException
-如果该类型是空的
public MutableCallSite(MethodHandle target)
target
-处理方法,将调用站点的初始目标
NullPointerException
如果提出的目标是零
public final MethodHandle getTarget()
MutableCallSite
。
对getTarget
与记忆的相互作用是一种从一个普通的变量,如数组元素或非易失性,非最终场。
特别是,当前的线程可以选择重用以前从内存中读取的目标的结果,并可能无法通过另一个线程看到一个最近的更新到目标。
getTarget
方法重写,继承类
CallSite
setTarget(java.lang.invoke.MethodHandle)
public void setTarget(MethodHandle newTarget)
与存储器的相互作用是相同的,如一个写入到一个普通的变量,如数组元素或非易失性,非最终字段。
特别是,不相关的线程可能会失败,看到更新的目标,直到他们执行一个从内存中读取。更强的保证,可以创建通过将适当的操作到引导方法和/或在任何给定的呼叫站点使用的目标方法。
setTarget
方法重写,继承类
CallSite
newTarget
-新目标
NullPointerException
如果提出的新目标是空的
WrongMethodTypeException
如果提出新的目标有一个方法类型,不同于以往的目标
getTarget()
public final MethodHandle dynamicInvoker()
此方法相当于下面的代码:
MethodHandle getTarget, invoker, result; getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class)); invoker = MethodHandles.exactInvoker(this.type()); result = MethodHandles.foldArguments(invoker, getTarget)
dynamicInvoker
方法重写,继承类
CallSite
public static void syncAll(MutableCallSite[] sites)
此操作不改变已启动旧目标值的任何调用。(java支持forward time travel而已。)
总的效果是迫使所有未来的读者的每个调用网站的目标接受最新存储的值。(“最近”,相对于syncAll
本身。)相反,的syncAll
调用可能会阻塞直到所有的读者都(可能)decached每个电话网站的目标之前的所有版本。
为了避免竞争条件,要求setTarget
和syncAll
一般应该是某种相互排斥的条件下进行。注意,读线程可以观察一个更新的目标早在setTarget
电话安装价值(和之前的syncAll
确认的价值)。另一方面,读者线程可以观察目标以前的版本,直到syncAll
调用返回(和setTarget
试图传达更新后的版本)。
此操作可能是昂贵的,应谨慎使用。如果可能的话,它应该被缓冲用于调用站点的集合上的批处理。
如果sites
包含一个null元素,一NullPointerException
将提高。在这种情况下,数组中的一些非空元素可能在方法返回异常之前处理过。这些元素(如果有的话)是依赖于实现的。
下面的影响是显而易见的,每个调用点S
:
V
volatile变量被创建,并由当前线程写。正如jmm所定义的,这写的是一个全球性的同步事件。V
之前发生。(在某些实现中,这意味着当前线程执行全局发布操作。)S
当前的目标是以挥写V
之前发生。V
放(在一个具体实施方式)在全球同步的顺序。T
(除了当前线程)。如果T
执行同步动作A
后挥写V
(在全球同步的顺序),因此需要看到当前的目标S
,还是后来写的目标,如果它执行对S
目标读。这种约束被称为“同步顺序一致性”。V
不会删掉,尽管它的价值是不确定的,其读写的价值是没有用的。T
立即行动
A
后读
V
挥发性。在行动中
T
当地订货,这之前发生的任何未来的阅读
S
目标读。这是因为如果实现任意挑选读
S
的目标
T
,强迫读
V
先于它,从而保证新的目标值通信。
只要java内存模型的约束条件是服从,实现可能延迟一syncAll
操作完成时,其他线程(T
以上)继续使用S
的目标值。然而,实现(总是)鼓励避免活锁,并最终要求所有线程以更新的目标客户。
讨论:由于性能原因,syncAll
不是一个电话网站的虚拟方法,而是适用于一组调用站点。一些实现可能会产生一个大的固定开销成本,用于处理一个或多个同步操作,但每个额外的调用站点的一个小的增量成本。在任何情况下,这种操作可能是昂贵的,因为其他线程可能必须以某种方式被中断,以使他们注意到更新的目标值。然而,它可能会被观察到,一个单一的呼叫同步几个网站有相同的正式的影响,因为许多电话,每一个只是一个网站。
注:实施的MutableCallSite
简单的实现可以使用volatile变量的变动给网站的目标。在这样一个实现的方法,syncAll
可以没有模式,但它符合JMM行为上面记录。
sites
-调用站点同步阵列
NullPointerException
-如果
sites
数组引用为空或数组包含一个空
Submit a bug or feature
For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples.
Copyright © 1993, 2014, Oracle and/or its affiliates. All rights reserved.