Spec-Zone.ru › OpenJDK 8

Класс LambdaMetafactory

  • java.lang.Object
    • java.lang.invoke.LambdaMetafactory

public class LambdaMetafactory
extends Object

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

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

  • Связывание происходит при вызове методов в этом классе. Они принимают в качестве аргументов интерфейс, подлежащий реализации (обычно функциональный интерфейс, с одним абстрактным методом), имя и сигнатуру метода из этого интерфейса, подлежащего реализации, дескриптор метода, описывающий желаемое поведение реализации для этого метода, и, возможно, другую дополнительную метаданные, и создают CallSite, цель которого может быть использована для создания соответствующих функциональных объектов. Связывание может включать динамическую загрузку нового класса, реализующего целевой интерфейс. CallSite можно рассматривать как "фабрику" функциональных объектов, поэтому эти методы связывания называются "метафабриками".
  • Захват происходит при вызове цели CallSite, обычно через invokedynamic место вызова, создавая функциональный объект. Это может происходить многократно для одной фабрики CallSite. Захват может включать выделение нового функционального объекта или возвращение существующего функционального объекта. Поведение MethodHandle может иметь дополнительные параметры помимо параметров указанного метода интерфейса; эти параметры называются захваченными параметрами, которые должны быть предоставлены в качестве аргументов целевому объекту CallSite, и которые могут быть связаны с поведением MethodHandle в начале. Количество захваченных параметров и их типы определяются во время связывания.
  • Вызов происходит при вызове реализованного метода интерфейса на функциональном объекте. Это может происходить многократно для одного функционального объекта. Метод, на который ссылается поведение MethodHandle , вызывается с захваченными аргументами и любыми дополнительными аргументами, предоставленными при вызове, как если бы с помощью MethodHandle.invoke(Object...).

Иногда полезно ограничить набор входов или результатов, разрешённых при вызове. Например, когда обобщённый интерфейс 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 для подробностей.

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

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

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

  • Rd является интерфейсом
  • implMethod является прямым дескриптором метода
  • samMethodType и instantiatedMethodType имеют одинаковую арность 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

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

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

Поля

Модификатор и тип Поле и описание
static int FLAG_BRIDGES

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

static int FLAG_MARKERS

Флаг для альтернативных метафабрик, указывающий, что объект лямбда реализует другие маркерные интерфейсы помимо Serializable

static int FLAG_SERIALIZABLE

Флаг для альтернативных метафабрик, указывающий, что объект лямбда должен быть сериализуемым

Конструкторы

Конструктор и описание
LambdaMetafactory()

Методы

Модификатор и тип Метод и описание
static CallSite altMetafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, Object... args)

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

static CallSite metafactory(MethodHandles.Lookup caller, String invokedName, MethodType invokedType, MethodType samMethodType, MethodHandle implMethod, MethodType instantiatedMethodType)

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

Methods inherited from class java.lang.Object

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

Поля

FLAG_SERIALIZABLE

public static final int FLAG_SERIALIZABLE

Флаг для альтернативных метафабрик, указывающий, что объект лямбда должен быть сериализуем

См. также:
Значения константных полей

FLAG_MARKERS

public static final int FLAG_MARKERS

Флаг для альтернативных метафабрик, указывающий, что объект лямбда реализует другие маркерные интерфейсы помимо Serializable

См. также:
Значения константных полей

FLAG_BRIDGES

public static final int FLAG_BRIDGES

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

См. также:
Значения константных полей

Конструкторы

LambdaMetafactory

public LambdaMetafactory()

Методы

metafactory

public static CallSite metafactory(MethodHandles.Lookup caller,
                                   String invokedName,
                                   MethodType invokedType,
                                   MethodType samMethodType,
                                   MethodHandle implMethod,
                                   MethodType instantiatedMethodType)
                            throws LambdaConversionException

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

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

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

Параметры:
caller - Представляет контекст поиска с правами доступа вызывающего. При использовании с invokedynamic, он автоматически добавляется в стек виртуальной машиной.
invokedName - Имя метода для реализации. При использовании с invokedynamic, оно предоставляется NameAndType структуры InvokeDynamic и автоматически добавляется в стек виртуальной машиной.
invokedType - Ожидаемая сигнатура CallSite. Типы параметров представляют типы переменных захвата; возвращаемый тип — интерфейс для реализации. При использовании с invokedynamic, он предоставляется NameAndType структуры InvokeDynamic и автоматически добавляется в стек виртуальной машиной. В случае, если метод реализации является методом экземпляра и эта сигнатура имеет какие-либо параметры, первый параметр в сигнатуре вызова должен соответствовать получателю.
samMethodType - Подпись и возвращаемый тип метода, который должен реализовываться функциональным объектом.
implMethod - Прямая обработка метода, описывающая метод реализации, который должен быть вызван (с соответствующим преобразованием типов аргументов, типов возврата и с предварительно добавленными аргументами захвата к аргументам вызова) во время вызова.
instantiatedMethodType - Подпись и возвращаемый тип, который должен динамически применяться во время вызова. Он может быть таким же, как samMethodType, или может быть его специализацией.
Возвращает:
CallSite, целевой объект которого может использоваться для захвата, генерирования экземпляров интерфейса, названного invokedType
Исключение:
LambdaConversionException - Если какие-либо из правил связывания, описанных в above, нарушены

altMetafactory

public static CallSite altMetafactory(MethodHandles.Lookup caller,
                                      String invokedName,
                                      MethodType invokedType,
                                      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 invokedName,
                          MethodType invokedType,
                          Object... args)

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

CallSite altMetafactory(MethodHandles.Lookup caller,
                          String invokedName,
                          MethodType invokedType,
                          MethodType samMethodType,
                          MethodHandle implMethod,
                          MethodType instantiatedMethodType,
                          int flags,
                          int markerInterfaceCount,  // IF flags has MARKERS set
                          Class... markerInterfaces, // IF flags has MARKERS set
                          int bridgeCount,           // IF flags has BRIDGES set
                          MethodType... bridges      // IF flags has BRIDGES set
                          )

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

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

Каждый класс, названный markerInterfaces, подчиняется тем же ограничениям, что и Rd, возвращаемый тип invokedType, как описано в above. Каждый MethodType с именем bridges подчиняется тем же ограничениям, что и samMethodType, как описано в above.

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

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

  • Класс реализует интерфейс, указанный возвращаемым типом invokedType и любые интерфейсы, указанные в markerInterfaces
  • Класс объявляет методы с именем, указанным invokedName, и сигнатурой, указанной samMethodType, и дополнительными сигнатурами, указанными в bridges
  • Класс может переопределять методы из Object, и может реализовывать методы, связанные с сериализацией.
Параметры:
caller - Представляет контекст поиска с правами доступа вызывающего. При использовании с invokedynamic, он автоматически добавляется в стек виртуальной машиной.
invokedName - Имя метода для реализации. При использовании с invokedynamic, оно предоставляется NameAndType структуры InvokeDynamic и автоматически добавляется в стек виртуальной машиной.
invokedType - Ожидаемая сигнатура CallSite. Типы параметров представляют типы переменных захвата; возвращаемый тип — интерфейс для реализации. При использовании с invokedynamic, он предоставляется NameAndType структуры InvokeDynamic и автоматически добавляется в стек виртуальной машиной. В случае, если метод реализации является методом экземпляра и эта сигнатура имеет какие-либо параметры, первый параметр в сигнатуре вызова должен соответствовать получателю.
args - Массив Object[] содержащий необходимые аргументы samMethodType, implMethod, instantiatedMethodType, flags, и любые необязательные аргументы, как описано в altMetafactory(MethodHandles.Lookup, String, MethodType, Object...) выше}
Возвращает:
CallSite, целевой объект которого может использоваться для захвата, генерирования экземпляров интерфейса, названного invokedType
Исключение:
LambdaConversionException - Если какие-либо из правил связывания, описанных в above, нарушены

© 1993, 2020, 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.

Spec-Zone.ru

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