Spec-Zone.ru › OpenJDK 27

Класс SwitchPoint

java.lang.Object
java.lang.invoke.SwitchPoint
public class SwitchPoint extends Object

SwitchPoint — это объект, который может публиковать переходы состояний для других потоков. Точка переключения изначально находится в допустимом (valid) состоянии, но в любой момент может быть переведена в недопустимое (invalid) состояние. Инвалидацию нельзя отменить. Точка переключения может объединять защищённую пару (guarded pair) дескрипторов методов в защищённый делегатор (guarded delegator). Защищённый делегатор — это дескриптор метода, который делегирует вызов одному из исходных дескрипторов методов. Состояние точки переключения определяет, какой из них двоих получает делегирование.

Одна точка переключения может использоваться для управления любым количеством дескрипторов методов. (Следовательно, косвенно она может управлять любым количеством мест вызова.) Это достигается за счёт использования одной точки переключения в качестве фабрики для объединения любого количества пар защищённых дескрипторов методов в защищённые делегаторы.

Когда защищённый делегатор создаётся из защищённой пары, пара оборачивается в новый дескриптор метода M, который постоянно связан с создавшей его точкой переключения. Каждая пара состоит из целевого дескриптора T и резервного дескриптора F. Пока точка переключения действительна, вызовы к M делегируются T. После её инвалидации вызовы делегируются F.

Инвалидация является глобальной и немедленной, как если бы точка переключения содержала переменную volatile boolean, проверяемую при каждом вызове 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

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

Конструктор Описание
SwitchPoint()
Создаёт новую точку переключения.

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

Модификатор и тип Метод Описание
MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback)
Возвращает дескриптор метода, который всегда делегирует вызов либо целевому, либо резервному дескриптору.
boolean hasBeenInvalidated()
Определяет, была ли эта точка переключения уже инвалидирована.
static void invalidateAll(SwitchPoint[] switchPoints)
Переводит все указанные точки переключения в недопустимое состояние.

Методы, унаследованные от класса 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()
Приводит к тому, что текущий поток ожидает, пока он не будет разбужен, обычно путём уведомления или прерывания.
final void wait(long timeoutMillis)
Приводит к тому, что текущий поток ожидает, пока он не будет разбужен, обычно путём уведомления или прерывания, либо до истечения определённого количества реального времени.
final void wait(long timeoutMillis, int nanos)
Приводит к тому, что текущий поток ожидает, пока он не будет разбужен, обычно путём уведомления или прерывания, либо до истечения определённого количества реального времени.

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

SwitchPoint

public SwitchPoint()
Создаёт новую точку переключения.

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

hasBeenInvalidated

public boolean hasBeenInvalidated()
Определяет, была ли эта точка переключения уже инвалидирована.

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

Поскольку инвалидация является глобальной и немедленной операцией, выполнение этого запроса на действительной точке переключения должно быть внутренне синхронизировано со всеми другими потоками, которые могут вызвать инвалидацию. Поэтому этот запрос может быть ресурсоёмким. Рекомендуемый способ создания дескриптора метода со значением boolean, который опрашивает состояние инвалидации точки переключения s, заключается в вызове s.guardWithTest для дескрипторов методов constant true и false.

Возвращает:
true, если эта точка переключения была инвалидирована

guardWithTest

public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback)
Возвращает дескриптор метода, который всегда делегирует вызов либо целевому, либо резервному дескриптору. Дескриптор метода будет делегировать целевому дескриптору ровно до тех пор, пока точка переключения действительна. После этого он будет постоянно делегировать резервному.

Целевой и резервный дескрипторы должны иметь в точности одинаковый тип метода, и результирующий комбинированный дескриптор метода также будет иметь этот тип.

Параметры:
target - дескриптор метода, выбираемый точкой переключения, пока она действительна
fallback - дескриптор метода, выбираемый точкой переключения после её инвалидации
Возвращает:
комбинированный дескриптор метода, который всегда вызывает либо целевой, либо резервный дескриптор
Исключения:
NullPointerException - если любой из аргументов равен null
IllegalArgumentException - если типы двух методов не совпадают
См. также:
  • MethodHandles.guardWithTest(MethodHandle, MethodHandle, MethodHandle)

invalidateAll

public static void invalidateAll(SwitchPoint[] switchPoints)
Переводит все указанные точки переключения в недопустимое состояние. После выполнения этого вызова ни один поток не увидит ни одну из точек переключения в допустимом состоянии.

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

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

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

Примечание по реализации: Простые реализации SwitchPoint могут использовать закрытый MutableCallSite для публикации состояния точки переключения. В такой реализации метод invalidateAll может просто изменить цель места вызова и выполнить один вызов для синхронизации всех закрытых мест вызова.

Параметры:
switchPoints - массив мест вызова, подлежащих синхронизации
Исключения:
NullPointerException - если ссылка на массив switchPoints равна 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