Класс SwitchPoint
public class SwitchPoint extends Object
SwitchPoint — это объект, который может публиковать переходы состояния для других потоков. Точка переключения изначально находится в действительном состоянии, но в любой момент может быть переведена в недействительное состояние. Отмена действия недействительного состояния невозможна. Точка переключения может объединить защищённую пару дескрипторов методов в защищённый делегатор. Защищённый делегатор — это дескриптор метода, который делегирует вызов одному из исходных дескрипторов методов. Состояние точки переключения определяет, которому из двух будет делегирован вызов.
Одна точка переключения может использоваться для управления любым количеством дескрипторов методов. (Косвенно, следовательно, она может управлять любым количеством точек вызова.) Для этого одна точка переключения используется как фабрика, объединяющая любое количество пар защищённых дескрипторов методов в защищённые делегаторы.
При создании защищённого делегатора из защищённой пары эта пара оборачивается в новый дескриптор метода 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 |
Возвращает дескриптор метода, который всегда делегирует вызов целевому или резервному дескриптору. |
boolean |
hasBeenInvalidated() |
Определяет, была ли эта точка переключения переведена в недействительное состояние. |
static void |
invalidateAll |
Переводит все указанные точки переключения в недействительное состояние. |
Подробное описание конструкторов
SwitchPoint
public SwitchPoint()
Подробное описание методов
hasBeenInvalidated
public boolean hasBeenInvalidated()
Обсуждение: Поскольку действие необратимо, как только точка переключения начинает возвращать true для hasBeenInvalidated, она всегда будет делать это и в дальнейшем. С другой стороны, действительная точка переключения, видимая другим потокам, может быть переведена в недействительное состояние в любой момент по запросу другого потока.
Поскольку инвалидация — глобальная операция, выполняемая немедленно, выполнение этого запроса для действительной точки переключения должно быть внутренне упорядочено относительно выполнения любых других потоков, которые могут вызвать инвалидацию. Поэтому этот запрос может быть затратным. Рекомендуемый способ создания дескриптора метода с логическим значением, который запрашивает состояние инвалидации точки переключения s, — вызвать s.guardWithTest для дескрипторов методов constant, возвращающих true и false.
- Возвращает:
- true, если эта точка переключения переведена в недействительное состояние
guardWithTest
public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback)
Целевой и резервный дескрипторы должны иметь в точности одинаковый тип метода; полученный объединённый дескриптор метода также будет иметь этот тип.
- Параметры:
-
target— дескриптор метода, выбираемый точкой переключения, пока она действительна -
fallback— дескриптор метода, выбираемый точкой переключения после перехода в недействительное состояние - Возвращает:
- объединённый дескриптор метода, который всегда вызывает целевой или резервный дескриптор
- Вызывает исключение:
-
NullPointerException— если один из аргументов равен null -
IllegalArgumentException— если типы двух методов не совпадают - См. также:
invalidateAll
public static void invalidateAll(SwitchPoint[] switchPoints)
Эта операция, вероятно, является затратной, поэтому её следует использовать экономно. По возможности её следует откладывать для пакетной обработки наборов точек переключения.
Если switchPoints содержит элемент null, будет сгенерировано исключение NullPointerException. В этом случае некоторые ненулевые элементы массива могут быть обработаны до того, как метод завершится с ошибкой. Какие именно элементы (если таковые имеются) будут обработаны, зависит от реализации.
Обсуждение: По соображениям производительности invalidateAll — не виртуальный метод для одной точки переключения, а операция, применяемая к набору точек переключения. Некоторые реализации могут иметь значительные постоянные издержки при выполнении одной или нескольких операций инвалидации, но небольшие дополнительные издержки для каждой последующей инвалидации. В любом случае эта операция, вероятно, будет затратной, поскольку для того, чтобы другие потоки заметили обновлённое состояние точки переключения, их может потребоваться каким-либо образом прервать. Однако один вызов для инвалидации нескольких точек переключения имеет тот же формальный эффект, что и множество вызовов, каждый из которых применяется только к одной точке переключения.
Примечание по реализации: Простые реализации SwitchPoint могут использовать частный MutableCallSite для публикации состояния точки переключения. В такой реализации метод invalidateAll может просто изменить целевой объект точки вызова, а затем вызвать синхронизацию всех частных точек вызова один раз.
- Параметры:
-
switchPoints— массив точек вызова, которые требуется синхронизировать - Вызывает исключение:
-
NullPointerException— если ссылка на массивswitchPointsравна null или массив содержит null
© 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.
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/invoke/SwitchPoint.html