Класс 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, она всегда будет делать это в будущем. С другой стороны, валидная точка переключения, видимая другим потокам, может быть проинвалидирована в любой момент из-за запроса другого потока.
Поскольку инвалидация является глобальной и мгновенной операцией, выполнение этого запроса на валидной точке переключения должно быть внутренне последовательно связано с любыми другими потоками, которые могли бы вызвать инвалидацию. Поэтому этот запрос может быть дорогим. Рекомендуемый способ построения обработчика метода типа boolean, который запрашивает состояние инвалидации точки переключения s, состоит в вызове s.guardWithTest для обработчиков методов 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- если ссылка на массивswitchPointsnull или массив содержит null
© 1993, 2023, 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/21/docs/api/java.base/java/lang/invoke/SwitchPoint.html