Класс SwitchPoint
public class SwitchPoint extends Object
Объект, который может публиковать переходы состояния другим потокам. Точка переключения изначально находится в состоянии валид, но в любой момент может быть изменена на состояние инвалид. Отмену инвалидации нельзя выполнить. Точка переключения может объединять защищенную пару обработчиков методов в защищенного делегата. Защищённый делегат — это обработчик методов, который делегирует вызов одному из старых обработчиков методов. Состояние точки переключения определяет, какой из двух обработчиков получает делегирование.
Одна точка переключения может быть использована для управления произвольным количеством обработчиков методов. (Косвенно, следовательно, она может управлять произвольным количеством мест вызова.) Это делается путём использования единственной точки переключения в качестве фабрики для объединения произвольного числа пар защищённых обработчиков методов в защищённые делегаты.
Когда защищённый делегат создаётся из защищённой пары, пара инкапсулируется в новый обработчик методов 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. В этом случае некоторые не-null элементы массива могут быть обработаны до того, как метод вернёт значение с ошибкой. Какие именно элементы это (если таковые имеются) зависит от реализации.
Обсуждение: По соображениям производительности, 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://download.java.net/java/early_access/jdk24/docs/api/java.base/java/lang/invoke/SwitchPoint.html