Spec-Zone.ru › OpenJDK 21

Класс LambdaMetafactory

java.lang.Object
java.lang.invoke.LambdaMetafactory
public final class LambdaMetafactory extends Object

Методы для облегчения создания простых «функциональных объектов», реализующих один или несколько интерфейсов путём делегирования предоставленному MethodHandle, возможно после адаптации типов и частичной оценки аргументов. Эти методы обычно используются в качестве методов-bootstrap для invokedynamic мест вызова, для поддержки функций лямбда-выражений и ссылок на методы в языке программирования Java.

Непрямой доступ к поведению, заданному предоставленным MethodHandle, происходит поэтапно через три фазы:

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

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

    CallSite можно рассматривать как «фабрику» для функциональных объектов, поэтому эти методы связывания называются «метафабриками».

  • Захват происходит, когда цель CallSite вызывается, как правило, через invokedynamic место вызова, создавая функциональный объект. Это может произойти много раз для одной фабрики CallSite.

    Если поведение MethodHandle имеет дополнительные параметры, помимо параметров метода указанного интерфейса, эти параметры называются захваченными параметрами, которые необходимо предоставить в качестве аргументов целевому CallSite. Ожидаемое количество и типы захваченных параметров определяются во время связывания.

    Захват может включать выделение нового функционального объекта или возврат подходящего существующего функционального объекта. Идентификатор созданного объектом захвата непредсказуем, поэтому операции, чувствительные к идентификатору (такие как равенство ссылок, блокировка объектов и System.identityHashCode()), могут давать разные результаты в разных реализациях или даже при разных вызовах в одной и той же реализации.

  • Вызов происходит, когда вызывается реализованный метод интерфейса для функционального объекта. Это может произойти много раз для одного функционального объекта. Метод, на который ссылается реализация MethodHandle вызывается, передавая ему захваченные и входные аргументы. Результат метода возвращается.

Иногда полезно ограничивать набор входных данных или результатов, разрешенных при вызове. Например, когда общий интерфейс Predicate<T> параметризован как Predicate<String>, вход должен быть String, даже если реализуемый метод допускает любые Object. В момент связывания дополнительный параметр MethodType описывает «динамический» тип метода; при вызове аргументы и возможный результат проверяются по этому MethodType.

Этот класс предоставляет два типа методов связывания: стандартную версию (metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)) с оптимизированным протоколом и альтернативную версию altMetafactory(MethodHandles.Lookup, String, MethodType, Object...). Альтернативная версия является обобщением стандартной версии, предоставляя дополнительный контроль над поведением сгенерированных функциональных объектов через флаги и дополнительные аргументы. Альтернативная версия добавляет возможность управления следующими атрибутами функциональных объектов:

  • Несколько методов. Иногда полезно реализовать несколько вариантов подписи метода, связанных с адаптацией аргументов или типов возвращаемых значений. Это происходит, когда несколько различных виртуальных машин (ВМ) сигнатуры для метода логически считаются одним и тем же методом в языке. Флаг FLAG_BRIDGES указывает, что будет предоставлен список дополнительных MethodType , каждый из которых будет реализован созданным функциональным объектом. Эти методы будут иметь одинаковое имя и тип экземпляра.
  • Несколько интерфейсов. При необходимости, функциональный объект может реализовывать более одного интерфейса. (Эти дополнительные интерфейсы, как правило, маркерные интерфейсы без методов.) Флаг FLAG_MARKERS указывает, что будет предоставлен список дополнительных интерфейсов, каждый из которых должен быть реализован созданным функциональным объектом.
  • Сериализация. Сгенерированные функциональные объекты, как правило, не поддерживают сериализацию. Если нужно, FLAG_SERIALIZABLE может быть использован для указания того, что функциональные объекты должны быть сериализуемыми. Сериализуемые функциональные объекты будут использовать, как свою сериализованную форму, экземпляры класса SerializedLambda, что требует дополнительной помощи от класса захвата (класса, описанного параметром MethodHandles.Lookup параметр caller); см. SerializedLambda для получения подробностей.

Предположим, что аргументы связывания следующие:

  • factoryType (описывающий CallSite сигнатуру) имеет K параметров типов (D1..Dk) и тип возвращаемого значения Rd;
  • interfaceMethodType (описывающий тип реализуемого метода) имеет N параметров типов (U1..Un) и тип возвращаемого значения Ru;
  • implementation (MethodHandle предоставляющий реализацию) имеет M параметров типов (A1..Am) и тип возвращаемого значения Ra (если метод описывает метод экземпляра, тип метода этого обработчика методов уже включает дополнительный первый аргумент, соответствующий получателю);
  • dynamicMethodType (разрешающий ограничения на вызов) имеет N параметров типов (T1..Tn) и тип возвращаемого значения Rt.

Тогда следующие инварианты связывания должны выполняться:

  • interfaceMethodType и dynamicMethodType имеют одинаковую арность N, а для i=1..N, Ti и Ui - одинаковый тип, или Ti и Ui - оба ссылочные типы, и Ti является подтипом Ui
  • Либо Rt и Ru - один и тот же тип, либо оба являются ссылочными типами и Rt является подтипом Ru
  • K + N = M
  • Для i=1..K, Di = Ai
  • Для i=1..N, Ti может быть адаптирован к Aj, где j=i+k
  • Тип возврата Rt - пустой, или тип возврата Ra не пустой и может быть адаптирован к Rt

Кроме того, во время захвата, если implementation соответствует методу экземпляра, и есть какие-либо аргументы захвата (K > 0), то первый аргумент захвата (соответствующий получателю) должен быть не null.

Тип Q считается приводимым к типу S следующим образом:

приводимые типы
Q S Проверки на этапе связывания Проверки на этапе вызова
Примитивный Примитивный Q может быть преобразован в S с помощью расширяющего примитивного преобразования Нет
Примитивный Ссылочный S является супертипом Wrapper(Q) Преобразование из Wrapper(Q) в S
Ссылочный Примитивный для типов параметров: Q является обёрткой над примитивным типом и Primitive(Q) может быть расширено до S
для типов возврата: Если Q является обёрткой над примитивным типом, проверяется, что Primitive(Q) может быть расширено до S
Если Q не является обёрткой над примитивным типом, Q преобразуется в базовую обёртку Wrapper(S); например, Number для числовых типов
Ссылочный Ссылочный для типов параметров: S является супертипом Q
для типов возврата: нет
Преобразование из Q в S
Примечание API:
Эти методы связывания разработаны для поддержки оценки лямбда-выражений и ссылок на методы в языке Java. Для каждого лямбда-выражения или ссылки на метод в исходном коде существует целевой тип, который является функциональным интерфейсом. Оценка лямбда-выражения приводит к объекту его целевого типа. Рекомендуемый механизм для оценки лямбда-выражений заключается в разборе тела лямбда-выражения в метод, вызове динамического места вызова invokedynamic, чья статическая аргументная запись описывает единственный метод функционального интерфейса и дезагрированный метод реализации, и возвращает объект (объект лямбды), который реализует целевой тип. (Для ссылок на методы метод реализации — это просто метод-ссылка, разбор не требуется.)

Список аргументов метода реализации и список аргументов метода(ов) интерфейса могут отличаться по нескольким причинам. Методы реализации могут иметь дополнительные аргументы для учета аргументов, захваченных лямбда-выражением; могут также существовать различия, возникающие в результате разрешенных адаптаций аргументов, таких как преобразование, бокс, унбокс и расширение примитивных типов. (Адаптации varargs не обрабатываются метафабриками; они должны обрабатываться вызывающим методом.)

У мест вызова invokedynamic есть два списка аргументов: статический и динамический. Статический список аргументов хранится в пуле констант; динамический аргумент помещается в стек операндов во время захвата. Метод bootstrap имеет доступ ко всему статическому списку аргументов (который в данном случае включает информацию о методе реализации, целевом интерфейсе и целевом методе(ах) интерфейса), а также к подписи метода, описывающей количество и статические типы (но не значения) динамических аргументов и статический тип возврата места вызова invokedynamic.

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

С:
1.8
END_OF_DOCUMENT_MARKER ```

Краткое описание полей

Модификатор и тип Поле Описание
static final int FLAG_BRIDGES
Флаг для альтернативных метафабрик, указывающий, что объект лямбда-выражения требует дополнительных методов, вызывающих implementation
static final int FLAG_MARKERS
Флаг для altMetafactory(java.lang.invoke.MethodHandles.Lookup, java.lang.String, java.lang.invoke.MethodType, java.lang.Object...), указывающий, что объект лямбда-выражения реализует другие интерфейсы помимо Serializable
static final int FLAG_SERIALIZABLE
Флаг для altMetafactory(java.lang.invoke.MethodHandles.Lookup, java.lang.String, java.lang.invoke.MethodType, java.lang.Object...), указывающий, что объект лямбда-выражения должен быть сериализуемым

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

Модификатор и тип Метод Описание
static CallSite altMetafactory(MethodHandles.Lookup caller, String interfaceMethodName, MethodType factoryType, Object... args)
Обеспечивает создание простых "функциональных объектов", которые реализуют один или несколько интерфейсов путём делегирования предоставленному MethodHandle, после соответствующей адаптации типов и частичной оценки аргументов.
static CallSite metafactory(MethodHandles.Lookup caller, String interfaceMethodName, MethodType factoryType, MethodType interfaceMethodType, MethodHandle implementation, MethodType dynamicMethodType)
Обеспечивает создание простых "функциональных объектов", которые реализуют один или несколько интерфейсов путём делегирования предоставленному MethodHandle, после соответствующей адаптации типов и частичной оценки аргументов.

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

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Подробное описание полей

FLAG_SERIALIZABLE

public static final int FLAG_SERIALIZABLE
Флаг для altMetafactory(java.lang.invoke.MethodHandles.Lookup, java.lang.String, java.lang.invoke.MethodType, java.lang.Object...), указывающий, что объект лямбда-выражения должен быть сериализуемым
См. также:
  • Значения константных полей

FLAG_MARKERS

public static final int FLAG_MARKERS
Флаг для altMetafactory(java.lang.invoke.MethodHandles.Lookup, java.lang.String, java.lang.invoke.MethodType, java.lang.Object...), указывающий, что объект лямбда-выражения реализует другие интерфейсы помимо Serializable
См. также:
  • Значения константных полей

FLAG_BRIDGES

public static final int FLAG_BRIDGES
Флаг для альтернативных метафабрик, указывающий, что объект лямбда-выражения требует дополнительных методов, вызывающих implementation
См. также:
  • Значения константных полей

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

metafactory

public static CallSite metafactory(MethodHandles.Lookup caller, String interfaceMethodName, MethodType factoryType, MethodType interfaceMethodType, MethodHandle implementation, MethodType dynamicMethodType) throws LambdaConversionException
Обеспечивает создание простых "функциональных объектов", которые реализуют один или несколько интерфейсов путём делегирования предоставленному MethodHandle, после соответствующей адаптации типов и частичной оценки аргументов. Обычно используется в качестве метода-загрузчика для invokedynamic вызовов, для поддержки лямбда-выражений и ссылок на методы в языке программирования Java.

Это стандартная, оптимизированная метафабрика; дополнительные возможности предоставляет altMetafactory(MethodHandles.Lookup, String, MethodType, Object...). Общее описание поведения этого метода представлено в above.

При вызове целевого объекта CallSite , возвращаемого этим методом, получаемые функциональные объекты являются экземплярами класса, реализующего интерфейс, указанный типом возврата factoryType, объявляющего метод с именем, заданным interfaceMethodName, и сигнатурой, заданной interfaceMethodType. Он также может переопределять дополнительные методы из Object.

Параметры:
caller - Представляет контекст поиска с правами доступа вызывающего объекта. В частности, контекст поиска должен иметь полные права доступа. При использовании с invokedynamic, это автоматически добавляется в стек виртуальной машины.
interfaceMethodName - Имя реализуемого метода. При использовании с invokedynamic, это предоставляется NameAndType структуры InvokeDynamic и автоматически добавляется в стек виртуальной машины.
factoryType - Ожидаемая сигнатура CallSite. Типы параметров представляют типы переменных захвата; тип возврата — реализуемый интерфейс. При использовании с invokedynamic, это предоставляется NameAndType структуры InvokeDynamic и автоматически добавляется в стек виртуальной машины.
interfaceMethodType - Подпись и тип возвращаемого значения реализуемого метода функциональным объектом.
implementation - Прямой метод-обработчик, описывающий реализуемый метод, который должен вызываться (с соответствующей адаптацией типов аргументов и типов возвращаемого значения, и с предварительно добавленными в вызов аргументами захваченных аргументов) во время вызова.
dynamicMethodType - Подпись и тип возвращаемого значения, которые должны быть динамически применены во время вызова. В простых случаях это то же, что и interfaceMethodType.
Возвращает:
объект CallSite, цель которого может быть использована для захвата, генерируя экземпляры интерфейса, указанного типом возврата factoryType
Исключения:
LambdaConversionException - Если caller не имеет полных прав доступа, или если interfaceMethodName не является допустимым именем метода JVM, или если тип возврата factoryType не является интерфейсом, или если implementation не является прямым методом-обработчиком, ссылающимся на метод или конструктор, или если нарушены связи, как определено в above.
NullPointerException - Если какой-либо аргумент null.
SecurityException - Если присутствует менеджер безопасности и он отклоняет доступ от caller к пакету implementation.

altMetafactory

public static CallSite altMetafactory(MethodHandles.Lookup caller, String interfaceMethodName, MethodType factoryType, Object... args) throws LambdaConversionException
Обеспечивает создание простых "функциональных объектов", которые реализуют один или несколько интерфейсов путем делегирования предоставленному MethodHandle после соответствующего преобразования типов и частичной оценки аргументов. Обычно используется в качестве метода-загрузчика для invokedynamic мест вызова, для поддержки функций выражений лямбда и ссылок на методы в языке программирования Java.

Это общий, более гибкий метафабрикатор; упрощенная версия предоставляется metafactory(java.lang.invoke.MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType). Общее описание поведения этого метода приведено в above.

Список аргументов для этого метода включает три фиксированных параметра, соответствующих параметрам, автоматически помещенным в стек ВМ для метода-загрузчика при вызове invokedynamic, и параметр Object[], содержащий дополнительные параметры. Объявленный список аргументов для этого метода:


  CallSite altMetafactory(MethodHandles.Lookup caller,
                          String interfaceMethodName,
                          MethodType factoryType,
                          Object... args)
 

но он ведет себя так, как будто список аргументов имеет следующий вид:


  CallSite altMetafactory(MethodHandles.Lookup caller,
                          String interfaceMethodName,
                          MethodType factoryType,
                          MethodType interfaceMethodType,
                          MethodHandle implementation,
                          MethodType dynamicMethodType,
                          int flags,
                          int altInterfaceCount,        // IF flags has MARKERS set
                          Class... altInterfaces,       // IF flags has MARKERS set
                          int altMethodCount,           // IF flags has BRIDGES set
                          MethodType... altMethods      // IF flags has BRIDGES set
                          )
 

Аргументы, которые появляются в списке аргументов для metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType), имеют ту же спецификацию, что и в этом методе. Дополнительные аргументы интерпретируются следующим образом:

  • flags указывает дополнительные параметры; это побитовое ИЛИ желаемых флагов. Определенные флаги: FLAG_BRIDGES, FLAG_MARKERS и FLAG_SERIALIZABLE.
  • altInterfaceCount — количество дополнительных интерфейсов, которые должен реализовать функциональный объект, и присутствует только в том случае, если установлен флаг FLAG_MARKERS.
  • altInterfaces — список дополнительных интерфейсов для реализации, длина которого равна altInterfaceCount, и присутствует только в том случае, если установлен флаг FLAG_MARKERS.
  • altMethodCount — количество дополнительных сигнатур методов, которые должен реализовать функциональный объект, и присутствует только в том случае, если установлен флаг FLAG_BRIDGES.
  • altMethods — список дополнительных сигнатур методов для реализации, длина которого равна altMethodCount, и присутствует только в том случае, если установлен флаг FLAG_BRIDGES.

Каждый класс, указанный в altInterfaces, подчиняется тем же ограничениям, что и Rd, тип возвращаемого значения factoryType, как описано в above. Каждый MethodType класс, указанный в altMethods, подчиняется тем же ограничениям, что и interfaceMethodType, как описано в above.

Когда в flags установлен флаг FLAG_SERIALIZABLE, функциональные объекты будут реализовывать Serializable, и будут иметь метод writeReplace, который возвращает соответствующий SerializedLambda. Класс caller должен иметь соответствующий метод $deserializeLambda$, как описано в SerializedLambda.

Когда целевой объект CallSite возвращаемый этим методом, вызывается, результирующие функциональные объекты являются экземплярами класса со следующими свойствами:

  • Класс реализует интерфейс, указанный типом возвращаемого значения factoryType и любыми интерфейсами, указанными в altInterfaces
  • Класс объявляет методы с именем, заданным в interfaceMethodName, и сигнатурой, заданной в interfaceMethodType, и дополнительными сигнатурами, заданными в altMethods
  • Класс может переопределять методы из Object, и может реализовывать методы, связанные с сериализацией.
Parameters:
caller - Представляет контекст поиска с привилегиями доступа вызывающего. В частности, контекст поиска должен иметь полный доступ. При использовании с invokedynamic, это автоматически добавляется в стек ВМ.
interfaceMethodName - Имя метода для реализации. При использовании с invokedynamic, это предоставляется NameAndType структуры InvokeDynamic и автоматически добавляется в стек ВМ.
factoryType - Ожидаемая сигнатура CallSite. Типы параметров представляют типы переменных захвата; тип возвращаемого значения — интерфейс для реализации. При использовании с invokedynamic, это предоставляется NameAndType структуры InvokeDynamic и автоматически добавляется в стек ВМ.
args - Массив Object содержащий необходимые аргументы interfaceMethodType, implementation, dynamicMethodType, flags, и любые необязательные аргументы, как описано выше
Returns:
a CallSite, целевой объект которого может использоваться для захвата, генерируя экземпляры интерфейса, указанного в factoryType
Throws:
LambdaConversionException - Если caller не имеет полного доступа, или interfaceMethodName не является допустимым именем метода JVM, или тип возвращаемого значения factoryType не является интерфейсом, или любой из altInterfaces не является интерфейсом, или implementation не является прямым обращением к методу или конструктору, или нарушены ограничения связывания, как определено above.
NullPointerException - Если любой аргумент или любой компонент args является null.
IllegalArgumentException - Если количество или типы компонентов args не соответствуют вышеуказанным правилам, или altInterfaceCount или altMethodCount являются отрицательными числами.
SecurityException - Если присутствует менеджер безопасности, и он отказывает в доступе от caller к пакету implementation.

© 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/LambdaMetafactory.html

Spec-Zone.ru

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