Spec-Zone.ru › OpenJDK 24

Класс LambdaMetafactory

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

Методы для облегчения создания простых «функциональных объектов», которые реализуют один или несколько интерфейсов путём делегирования предоставленному MethodHandle, возможно, после адаптации типов и частичной оценки аргументов. Эти методы обычно используются в качестве методов-bootstrap для invokedynamic мест вызова, для поддержки функций lambda-выражения и ссылка на метод в языке программирования 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 указывает, что будет предоставлен список дополнительных 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 в базовую обёртку(S); например Number для числовых типов
Ссылочный Ссылочный для типов параметров: S является супертипом Q
для типов возвращаемых значений: нет
Преобразование из Q в S
END_OF_DOCUMENT_MARKER
Примечание API:
Эти методы связывания предназначены для поддержки оценки лямбда-выражений и ссылок на методы в языке Java. Для каждого лямбда-выражения или ссылки на метод в исходном коде существует целевой тип, который является функциональным интерфейсом. Оценка лямбда-выражения приводит к созданию объекта его целевого типа. Рекомендуемый механизм для оценки лямбда-выражений заключается в преобразовании тела лямбда-выражения в метод, вызове вызова invokedynamic, у которого статический список аргументов описывает единственный метод функционального интерфейса и метод реализованного выражения, и возвращении объекта (объекта лямбда-выражения), который реализует целевой тип. (Для ссылок на методы реализующий метод — это просто указанный метод; преобразование не требуется.)

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

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

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

Использование, помимо оценки лямбда-выражений и ссылок на методы, не предполагается. Эти методы связывания могут изменять свои не указанные поведения в любое время, чтобы лучше соответствовать функциям языка Java, для поддержки которых они были разработаны, и такие изменения могут повлиять на непреднамеренное использование. Непреднамеренное использование этих методов связывания может привести к утечкам ресурсов или другим не определенным негативным последствиям.

Примечание реализации:
В эталонной реализации классы, реализующие созданные объекты функций, напрямую доступны из загрузчика классов вызывающей стороны, как классы и интерфейсы в исходном коде Java. Этот метод уменьшает использование памяти кучи, но в результате реализующие классы могут быть разгружены только в том случае, если вызывающий класс может быть разгружен. В частности, если вызывающий класс является слабым скрытым классом, реализующий класс, сильный скрытый класс, может не быть разгружен, даже если вызывающий класс может быть разгружен.
С:
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.

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.

Когда флаг FLAG_SERIALIZABLE установлен в flags, функциональные объекты будут реализовывать 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:
CallSite, целевой объект которого может использоваться для захвата, генерируя экземпляры интерфейса, указанного в factoryType
Throws:
LambdaConversionException - Если caller не имеет полного доступа, или если interfaceMethodName не является допустимым именем метода JVM, или если тип возврата factoryType не является интерфейсом, или если любой из altInterfaces не является интерфейсом, или если implementation не является прямым обработчиком метода, ссылающимся на метод или конструктор, или если нарушены инварианты связывания, как определено в above.
NullPointerException - Если какой-либо аргумент или компонент args некорректен.
IllegalArgumentException - Если количество или типы компонентов args не соответствуют вышеуказанным правилам, или если altInterfaceCount или altMethodCount являются отрицательными целыми числами.

Сообщить об ошибке или предложить улучшение
Для дополнительной справки по API и документации для разработчиков см. Документацию Java SE, которая содержит более подробные описания для разработчиков с концептуальными обзорами, определениями терминов, решениями и примерами кода. Другие версии.
Java — товарный знак или зарегистрированный товарный знак Oracle и/или ее дочерних компаний в США и других странах.
Copyright © 1993, 2025, Oracle и/или ее дочерние компании, 500 Oracle Parkway, Redwood Shores, CA 94065 США.
Все права защищены. Использование регулируется условиями лицензии и политикой перераспределения документации.
DRAFT 24-ea+36-Debian-1

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

Spec-Zone.ru

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