Spec-Zone.ru › OpenJDK 17

Класс 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...). Альтернативная версия обобщает стандартную версию, предоставляя дополнительный контроль над поведением созданных функциональных объектов с помощью флагов и дополнительных аргументов. Альтернативная версия добавляет возможность управления следующими атрибутами функциональных объектов:

  • Несколько методов. Иногда полезно реализовать несколько вариантов сигнатуры метода, используя адаптацию аргументов или типов возврата. Это происходит, когда несколько различных сигнатур VM для метода логически считаются одним и тем же методом в языке. Флаг FLAG_BRIDGES указывает, что будет предоставлен список дополнительных MethodTypes, каждый из которых будет реализован полученным функциональным объектом. Эти методы будут использовать одно и то же имя и экземплярный тип.
  • Несколько интерфейсов. При необходимости функциональный объект может реализовывать более одного интерфейса. (Эти дополнительные интерфейсы обычно являются интерфейсами-маркерами без методов.) Флаг 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 равен null, или тип возврата Ra не равен null и адаптируется к 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

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

Модификатор и тип Поле Описание
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.

Список аргументов этого метода включает три фиксированных параметра, соответствующих параметрам, автоматически помещаемым в стек JVM для метода-загрузчика при вызове 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.

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

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

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

© 1993, 2021, 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/17/docs/api/java.base/java/lang/invoke/LambdaMetafactory.html

Spec-Zone.ru

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