Spec-Zone.ru › OpenJDK 27

Класс MutableCallSite

java.lang.Object
java.lang.invoke.CallSite
java.lang.invoke.MutableCallSite
Прямые известные подклассы:
AbstractRelinkableCallSite
public non-sealed class MutableCallSite extends CallSite
MutableCallSite — это CallSite, целевая переменная которого ведёт себя как обычное поле. Инструкция invokedynamic, связанная с MutableCallSite, перенаправляет все вызовы к текущей цели сайта. Динамический вызов изменяемого сайта вызовов также перенаправляет каждый вызов к текущей цели сайта.

Ниже приведён пример изменяемого сайта вызовов, который вводит переменную состояния в цепочку дескрипторов методов.

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-сайта вызовов.

С момента выпуска:
1.7

Краткое описание конструкторов

Конструктор Описание
MutableCallSite(MethodHandle target)
Создаёт объект сайта вызовов с начальным дескриптором целевого метода.
MutableCallSite(MethodType type)
Создаёт пустой объект сайта вызовов с указанным типом метода.

Краткое описание методов

Модификатор и тип Метод Описание
final MethodHandle dynamicInvoker()
Создаёт дескриптор метода, эквивалентный инструкции invokedynamic, связанной с этим сайтом вызовов.
final MethodHandle getTarget()
Возвращает целевой метод сайта вызовов, который ведёт себя как обычное поле MutableCallSite.
void setTarget(MethodHandle newTarget)
Обновляет целевой метод этого сайта вызовов как обычную переменную.
static void syncAll(MutableCallSite[] sites)
Выполняет операцию синхронизации для каждого сайта вызовов в указанном массиве, заставляя все остальные потоки отбросить любые кэшированные значения, ранее загруженные из цели любого из этих сайтов вызовов.

Методы, объявленные в классе CallSite

type
Модификатор и тип Метод Описание
MethodType type()
Возвращает тип цели этого сайта вызовов.

Методы, объявленные в классе Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
Модификатор и тип Метод Описание
protected Object clone()
Создаёт и возвращает копию этого объекта.
boolean equals(Object obj)
Показывает, равен ли какой-либо другой объект этому объекту.
protected void finalize()
Устарел, будет удалён: этот элемент API подлежит удалению в будущей версии.
Финализация устарела и подлежит удалению в одном из будущих выпусков.
final Class<?> getClass()
Возвращает класс времени выполнения этого Object.
int hashCode()
Возвращает хеш-код этого объекта.
final void notify()
Пробуждает один поток, ожидающий на мониторе этого объекта.
final void notifyAll()
Пробуждает все потоки, ожидающие на мониторе этого объекта.
String toString()
Возвращает строковое представление объекта.
final void wait()
Заставляет текущий поток ожидать пробуждения, обычно посредством вызова notify или interrupt.
final void wait(long timeoutMillis)
Заставляет текущий поток ожидать пробуждения, обычно посредством вызова notify или interrupt, либо до истечения заданного интервала реального времени.
final void wait(long timeoutMillis, int nanos)
Заставляет текущий поток ожидать пробуждения, обычно посредством вызова notify или interrupt, либо до истечения заданного интервала реального времени.

Подробное описание конструкторов

MutableCallSite

public MutableCallSite(MethodType type)
Создаёт пустой объект сайта вызовов с указанным типом метода. Начальная цель задаётся дескриптором метода указанного типа, который при вызове выбрасывает исключение IllegalStateException.

Тип сайта вызовов задаётся указанным типом без возможности последующего изменения.

Прежде чем этот объект CallSite будет возвращён из метода начальной загрузки или вызван каким-либо иным способом, ему обычно назначают более полезный целевой метод посредством вызова setTarget.

Параметры:
type — тип метода, который будет иметь этот сайт вызовов
Выбрасывает:
NullPointerException — если предложенный тип равен null

MutableCallSite

public MutableCallSite(MethodHandle target)
Создаёт объект сайта вызовов с начальным дескриптором целевого метода. Тип сайта вызовов задаётся типом начальной цели без возможности последующего изменения.
Параметры:
target — дескриптор метода, который будет начальной целью сайта вызовов
Выбрасывает:
NullPointerException — если предложенная цель равна null

Подробное описание методов

getTarget

public final MethodHandle getTarget()
Возвращает целевой метод сайта вызовов, который ведёт себя как обычное поле MutableCallSite.

Взаимодействие getTarget с памятью такое же, как при чтении обычной переменной, например элемента массива или поля, не являющегося volatile или final.

В частности, текущий поток может повторно использовать результат предыдущего чтения цели из памяти и может не увидеть недавнее обновление цели, выполненное другим потоком.

Переопределяет:
getTarget в классе CallSite
Возвращает:
состояние связывания этого сайта вызовов — дескриптор метода, который может изменяться со временем
См. также:
  • setTarget(MethodHandle)

setTarget

public void setTarget(MethodHandle newTarget)
Обновляет целевой метод этого сайта вызовов как обычную переменную. Тип новой цели должен совпадать с типом старой цели.

Взаимодействие с памятью такое же, как при записи обычной переменной, например элемента массива или поля, не являющегося volatile или final.

В частности, несвязанные потоки могут не увидеть обновлённую цель, пока не выполнят чтение из памяти. Более строгие гарантии можно обеспечить, добавив соответствующие операции в метод начальной загрузки и/или целевые методы, используемые в данном сайте вызовов.

Переопределяет:
setTarget в классе CallSite
Параметры:
newTarget — новая цель
Выбрасывает:
NullPointerException — если предложенная новая цель равна null
WrongMethodTypeException — если тип метода предложенной новой цели отличается от типа предыдущей цели
См. также:
  • getTarget()

dynamicInvoker

public final MethodHandle 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)
Переопределяет:
dynamicInvoker в классе CallSite
Возвращает:
дескриптор метода, который всегда вызывает текущую цель этого сайта вызовов

syncAll

public static void syncAll(MutableCallSite[] sites)
Выполняет операцию синхронизации для каждого сайта вызовов в указанном массиве, заставляя все остальные потоки отбросить любые кэшированные значения, ранее загруженные из цели любого из этих сайтов вызовов.

Эта операция не отменяет вызовы, уже начатые с использованием старого значения цели. (Java поддерживает только перемещение вперёд во времени.)

Общий эффект состоит в том, чтобы заставить всех будущих читателей цели каждого сайта вызовов принять последнее сохранённое значение. («Последнее» определяется относительно самой операции syncAll.) И наоборот, вызов syncAll может блокироваться до тех пор, пока все читатели каким-либо образом не сбросят кэшированные предыдущие версии цели каждого сайта вызовов.

Во избежание состязаний вызовы setTarget и syncAll обычно следует выполнять под какой-либо взаимной блокировкой. Обратите внимание, что потоки-читатели могут увидеть обновлённую цель уже во время вызова setTarget, устанавливающего значение (до вызова syncAll, подтверждающего это значение). С другой стороны, потоки-читатели могут наблюдать предыдущие версии цели до возврата вызова syncAll (и после вызова setTarget, который пытается передать обновлённую версию).

Эта операция, вероятно, затратна и должна использоваться редко. Если возможно, её следует буферизовать для пакетной обработки наборов сайтов вызовов.

Если sites содержит элемент null, будет выброшено исключение NullPointerException. В этом случае до аварийного завершения метода могут быть обработаны некоторые ненулевые элементы массива. Какие именно элементы (если таковые будут) обработаны, зависит от реализации.

Подробные сведения о модели памяти Java

С точки зрения модели памяти Java эта операция выполняет действие синхронизации, эффект которого сопоставим с записью volatile-переменной текущим потоком и последующим чтением volatile-переменной каждым другим потоком, который может обращаться к одному из затронутых сайтов вызовов.

Для каждого отдельного сайта вызовов S очевидны следующие эффекты:

  • Создаётся новая volatile-переменная V, в которую выполняет запись текущий поток. Согласно JMM, эта запись является глобальным событием синхронизации.
  • Как обычно при упорядочивании событий записи в потоке, считается, что каждое действие, уже выполненное текущим потоком, происходит до volatile-записи в V. (В некоторых реализациях это означает, что текущий поток выполняет глобальную операцию освобождения.)
  • В частности, запись текущей цели S считается происходящей до volatile-записи в V.
  • Volatile-запись в V помещается (зависящим от реализации способом) в глобальный порядок синхронизации.
  • Рассмотрим произвольный поток T (не являющийся текущим потоком). Если T выполняет действие синхронизации A после volatile-записи в V (в глобальном порядке синхронизации), то при чтении цели S он обязан увидеть текущую цель S или более позднюю запись в эту цель. (Это ограничение называется «согласованностью порядка синхронизации».)
  • JMM прямо разрешает оптимизирующим компиляторам исключать чтения или записи переменных, заведомо не имеющие смысла. Такие исключённые чтения и записи не влияют на отношение «происходит до». Несмотря на это, volatile-переменная V не будет исключена, хотя записываемое в неё значение неопределённо, а прочитанное значение не используется.
Из-за последнего пункта реализация ведёт себя так, как если бы T выполнял volatile-чтение V непосредственно после своего действия A. В локальном порядке действий T это чтение происходит до любого последующего чтения цели S. Это равносильно тому, как если бы реализация произвольно выбрала чтение цели S потоком T и заставила чтение V предшествовать ему, тем самым обеспечив передачу нового значения цели.

Пока соблюдаются ограничения модели памяти Java, реализации могут задерживать завершение операции syncAll, в то время как другие потоки (T выше) продолжают использовать предыдущие значения цели S. Однако реализации (как и всегда) рекомендуется избегать livelock и в конечном итоге обеспечить учёт обновлённой цели всеми потоками.

Обсуждение: Из соображений производительности syncAll является не виртуальным методом для одного сайта вызовов, а применяется к набору сайтов вызовов. В некоторых реализациях обработка одной или нескольких операций синхронизации может иметь большие фиксированные накладные расходы, но небольшие дополнительные расходы для каждого последующего сайта вызовов. В любом случае эта операция, вероятно, будет затратной, поскольку для того, чтобы другие потоки заметили обновлённое значение цели, их, возможно, придётся каким-либо образом прервать. Однако следует учитывать, что один вызов для синхронизации нескольких сайтов имеет тот же формальный эффект, что и множество вызовов, каждый из которых применяется только к одному сайту.

Примечание по реализации: Простые реализации MutableCallSite могут использовать volatile-переменную для цели изменяемого сайта вызовов. В такой реализации метод syncAll может быть пустой операцией и при этом соответствовать описанному выше поведению JMM.

Параметры:
sites — массив сайтов вызовов для синхронизации
Выбрасывает:
NullPointerException — если ссылка sites на массив равна null или массив содержит null

Сообщить об ошибке или предложить улучшение
Дополнительные справочные материалы по API и документацию для разработчиков см. в разделе документации Java SE, содержащем более подробные описания для разработчиков, концептуальные обзоры, определения терминов, обходные решения и примеры работающего кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или её аффилированных лиц в США и других странах.
Авторское право © 1993, 2026, Oracle и/или её аффилированные лица, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API