Spec-Zone .ru
спецификации, руководства, описания, API
|
public class MutableCallSite extends CallSite
MutableCallSite
a CallSite
чья целевая переменная ведет себя как обычное поле. invokedynamic
инструкция, соединенная с a MutableCallSite
делегаты все звонки в текущую цель сайта. Динамический 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
работа обеспечивает способ вынудить потоки принять новое целевое значение, даже если нет никакой другой синхронизации.
Для целевых значений, которые будут часто обновляться, рассмотрите использование энергозависимого сайта вызова вместо этого.
Конструктор и Описание |
---|
MutableCallSite(MethodHandle target)
Создает объект сайта вызова с начальным целевым дескриптором метода.
|
MutableCallSite(MethodType type)
Создает пустой объект сайта вызова с данным типом метода.
|
Модификатор и Тип | Метод и Описание |
---|---|
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 поддерживает прямое путешествие во времени только.)
Полный эффект состоит в том, чтобы вынудить всех будущих читателей каждой цели сайта вызова принять последний раз хранимую сумму. ("Последний раз" считается относительно syncAll
непосредственно.) Наоборот, syncAll
вызов может блокировать, пока у всех читателей нет (так или иначе) decached всех предыдущих версий каждой цели сайта вызова.
Чтобы избежать условий гонки, призывает setTarget
и syncAll
должен обычно быть выполнен под своего рода взаимным исключением. Отметьте, что потоки читателя уже могут наблюдать обновленную цель setTarget
вызовите ту установку значение (и перед syncAll
это подтверждает значение). С другой стороны потоки читателя могут наблюдать предыдущие версии цели до syncAll
вызовите возвраты (и после setTarget
это пытается передать обновленную версию).
Эта работа, вероятно, будет дорога и должна использоваться экономно. Если возможный, это должно быть буферизовано для пакетной обработки на наборах сайтов вызова.
Если sites
содержит нулевой элемент, a NullPointerException
будет повышен. В этом случае некоторые ненулевые элементы в массиве могут быть обработаны прежде, чем метод возвращается неправильно. То, какие элементы они (если любой) является зависящим от реализации.
Следующие эффекты очевидны для каждого отдельного сайта вызова S
:
V
создается, и пишется текущим потоком. Как определено JMM, эта запись является глобальным событием синхронизации. V
. (В некоторых реализациях это означает, что текущий поток выполняет глобальную работу выпуска.) S
берется, чтобы произойти перед энергозависимой записью с V
. V
помещается (в реализации определенный способ) в глобальном порядке синхронизации. T
(кроме текущего потока). Если T
выполняет действие синхронизации A
после энергозависимой записи к V
(в глобальном порядке синхронизации), это поэтому обязано видеть любого текущая цель S
, или более поздняя запись к той цели, если это выполняет чтение на цели S
. (Это ограничение вызывают "непротиворечивостью порядка синхронизации".) V
не будет игнорироваться, даже при том, что его записанное значение неопределенно, и его значение чтения не используется. V
выполнялись T
сразу после его действия A
. В локальном упорядочивании действий в T
, это чтение происходит перед любым будущим чтением цели S
. Это как будто реализация, произвольно выбранная чтение S
's предназначаются T
, и вызванный чтение V
предшествовать этому, таким образом гарантируя передачу нового целевого значения. Пока ограничениям Модели Памяти Java повинуются, реализации могут задержать завершение a syncAll
работа, в то время как другие потоки (T
выше), продолжают использовать предыдущие значения S
's цель. Однако, реализации (как всегда) поощрены избежать динамической взаимоблокировки, и в конечном счете потребовать, чтобы все потоки приняли во внимание обновленную цель.
Обсуждение: По причинам производительности, syncAll
не виртуальный метод на единственном сайте вызова, а скорее применяется к ряду сайтов вызова. Некоторые реализации могут подвергнуться крупному фиксированному накладному расходу на обработку одной или более операций синхронизации, но маленькой инкрементной стоимости для каждого дополнительного сайта вызова. В любом случае эта работа, вероятно, будет дорогостоящей, так как другие потоки, вероятно, придется так или иначе прервать, чтобы заставить их заметить обновленное целевое значение. Однако, можно заметить, что единственный вызов, чтобы синхронизировать несколько сайтов имеет тот же самый формальный эффект так много вызовов, каждый на только одном из сайтов.
Примечание реализации: Простые реализации MutableCallSite
может использовать энергозависимую переменную для цели изменчивого сайта вызова. В такой реализации, syncAll
метод может быть не, и все же он будет соответствовать поведению JMM, задокументированному выше.
sites
- массив сайтов вызова, которые будут синхронизироватьсяNullPointerException
- если sites
ссылка массива является нулем, или массив содержит нуль
Для дальнейшей ссылки API и документации разработчика, см.
Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.