Spec-Zone.ru › OpenJDK 17

Пакет java.lang.invoke

package java.lang.invoke
Пакет java.lang.invoke предоставляет примитивы низкого уровня для взаимодействия с виртуальной машиной Java.

Как описано в спецификации виртуальной машины Java, определённые типы в этом пакете получают специальное обращение от виртуальной машины:

  • Классы MethodHandle и VarHandle содержат полиморфные по сигнатуре методы, которые могут быть связаны независимо от их описателя типа. Обычно связывание метода требует точного совпадения описателей типов.
  • Формат байткода JVM поддерживает непосредственные константы классов MethodHandle и MethodType.
  • Инструкция invokedynamic использует константы-загрузчики MethodHandle для динамического разрешения объектов CallSite для поведения вызова пользовательских методов.
  • Инструкция ldc использует константы-загрузчики MethodHandle для динамического разрешения пользовательских константных значений.

Динамическое разрешение сайтов вызовов и констант

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

Динамически вычисляемые сайты вызовов

Инструкция invokedynamic изначально находится в несвязанном состоянии. В этом состоянии нет целевого метода для вызова инструкцией.

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

Каждая инструкция invokedynamic статически определяет свой собственный метод загрузки как ссылку на пул констант. Ссылка на пул констант также определяет имя вызова и описатель типа метода, подобно invokestatic и другим инструкциям вызова.

Динамически вычисляемые константы

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

Каждая динамически вычисляемая константа статически определяет свой собственный метод загрузки как ссылку на пул констант. Ссылка на пул констант также определяет имя константы и описатель типа поля, подобно getstatic и другим инструкциям ссылки на поля. (Грубо говоря, динамически вычисляемая константа относится к динамически вычисляемому сайту вызова как CONSTANT_Fieldref к CONSTANT_Methodref.)

Выполнение методов загрузки

Разрешение динамически вычисляемого сайта вызова или константы начинается с разрешения констант из пула констант для следующих элементов:
  • метод загрузки, являющийся CONSTANT_MethodHandle
  • типы Class или MethodType, полученные из компонента типа описателя CONSTANT_NameAndType
  • статические аргументы, если таковые имеются (обратите внимание, что статические аргументы могут сами быть динамически вычисляемыми константами)

Затем метод загрузки вызывается, как если бы он был вызван с помощью MethodHandle.invoke, со следующими аргументами:

  • объект поиска, который является объектом поиска в классе вызывающего, в котором происходит динамически вычисляемая константа или сайт вызова
  • имя, упомянутое в CONSTANT_NameAndType
  • описатель типа MethodType или Class, разрешенный описатель типа CONSTANT_NameAndType
  • разрешенный описатель типа константы, если это динамическая константа
  • дополнительные разрешенные статические аргументы, если таковые имеются

Для динамически вычисляемого сайта вызова возвращаемое значение должно быть ссылкой на не-null объект CallSite. Тип целевого сайта вызова должен быть точно равен типу, полученному из описателя типа вызова и переданному методу загрузки. Если эти условия не выполнены, выбрасывается BootstrapMethodError. При успехе сайт вызова становится постоянно связанным с инструкцией invokedynamic.

Для динамически вычисляемой константы первый параметр метода загрузки должен быть присваиваемым к MethodHandles.Lookup. Если это условие не выполнено, выбрасывается BootstrapMethodError. При успехе результат метода загрузки кэшируется как значение разрешённой константы.

Если во время выполнения метода загрузки возникает исключение, например, E, разрешение завершается аварийно. E перебрасывается, если тип E равен Error или его подклассу, в противном случае выбрасывается BootstrapMethodError, который оборачивает E. В этом случае та же ошибка будет выбрасываться при всех последующих попытках выполнить инструкцию invokedynamic или загрузить динамически вычисляемую константу.

Время разрешения

Инструкция invokedynamic связывается непосредственно перед её первым выполнением. Динамически вычисляемая константа разрешается непосредственно перед первым использованием (путём её помещения на стек или связывания в качестве параметра метода загрузки). Вызов метода загрузки, реализующий связывание, происходит в потоке, который пытается выполнить первое выполнение или первое использование.

Если существует несколько таких потоков, метод загрузки может быть вызван в нескольких потоках одновременно. Следовательно, методы загрузки, которые обращаются к глобальным данным приложения, должны принимать обычные меры предосторожности против гонок. В любом случае, каждая инструкция invokedynamic либо не связана, либо связана с уникальным объектом CallSite.

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

Если несколько потоков одновременно выполняют метод загрузки для одного динамически вычисляемого сайта вызова или константы, JVM должна выбрать один результат метода загрузки и установить его видимым для всех потоков. Любые другие вызовы методов загрузки разрешены для завершения, но их результаты игнорируются.

Обсуждение: Эти правила не позволяют JVM совместно использовать сайты вызовов или выполнять вызовы методов загрузки «без причины». Каждая инструкция invokedynamic переходит не более чем один раз от несвязанного к связанному состоянию, непосредственно перед своим первым вызовом. Нет способа отменить действие завершённого вызова метода загрузки.

Типы методов загрузки

Для динамически вычисляемого сайта вызова метод загрузки вызывается с параметрами типов MethodHandles.Lookup, String, MethodType, и типами любых статических аргументов; тип возвращаемого значения CallSite.

Для динамически вычисляемой константы метод загрузки вызывается с параметрами типов MethodHandles.Lookup, String, Class, и типами любых статических аргументов; тип возвращаемого значения представляет тип Class.

Поскольку MethodHandle.invoke позволяет адаптации между типом вызываемого метода и типом метода обработчика загрузки, существует гибкость в объявлении метода загрузки. Для динамически вычисляемой константы первый тип параметра метода загрузки должен быть присваиваемым к MethodHandles.Lookup, за исключением этого ограничения, та же степень гибкости применяется к методам загрузки динамически вычисляемых сайтов вызова и динамически вычисляемых констант. Примечание: это ограничение позволяет в будущем возможность вызова метода загрузки только с типами параметров статических аргументов, тем самым поддерживая более широкий диапазон методов, совместимых со статическими аргументами (таких как методы, которые не объявляют или не требуют параметров метаданных поиска, имени и типа).

Например, для динамически вычисляемого сайта вызова первым аргументом может быть Object вместо MethodHandles.Lookup, а тип возвращаемого значения также может быть Object вместо CallSite. (Обратите внимание, что типы и количество аргументов стека ограничивают допустимые типы методов загрузки до статических методов и конструкторов соответствующих типов).

Если введённое значение является примитивным типом, оно может быть преобразовано в ссылку путём преобразования упаковки. Если метод загрузки является методом с переменным количеством аргументов (его модификатор 0x0080 установлен), то некоторые или все аргументы, указанные здесь, могут быть собраны в параметр массива. (Это не специальное правило, а скорее полезное следствие взаимодействия между константами CONSTANT_MethodHandle, модификатором бита для методов с переменным количеством аргументов и преобразованием asVarargsCollector.)

Учитывая эти правила, вот примеры допустимых объявлений методов загрузки для динамически вычисляемых сайтов вызова, учитывая различное количество N дополнительных аргументов. Первый ряд (отмеченный *) будет работать для любого количества дополнительных аргументов.

Типы статических аргументов
N Пример метода загрузки
*
  • CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)
  • CallSite bootstrap(Object... args)
  • CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs)
0
  • CallSite bootstrap(Lookup caller, String name, MethodType type)
  • CallSite bootstrap(Lookup caller, Object... nameAndType)
1 CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg)
2
  • CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)
  • CallSite bootstrap(Lookup caller, String name, MethodType type, String... args)
  • CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)
Последний пример предполагает, что дополнительные аргументы являются типов String и Integer (или int), соответственно. Предшествующий ему пример предполагает, что все дополнительные аргументы являются типа String. Другие примеры работают со всеми типами дополнительных аргументов. Обратите внимание, что все примеры, кроме второго и третьего, также работают с динамически вычисляемыми константами, если тип возвращаемого значения изменяется для совместимости с объявленным типом константы (например, Object, который всегда совместим).

Поскольку динамически вычисляемые константы могут предоставляться в качестве статических аргументов методам загрузки, нет ограничений на типы аргументов загрузки. Однако аргументы типа boolean, byte, short, или char не могут быть непосредственно предоставлены записями пула констант CONSTANT_Integer, так как преобразования asType не выполняют необходимые сужающие преобразования примитивных типов.

В приведенных выше примерах возвращаемый тип всегда CallSite, но это не является обязательным свойством методов загрузки. В случае вызова динамически вычисляемой целевой точки единственное требование состоит в том, что возвращаемый тип метода загрузки должен быть преобразуем (с использованием преобразований asType) к CallSite, что означает, что возвращаемый тип метода загрузки может быть Object или ConstantCallSite. В случае динамически разрешенной константы возвращаемый тип метода загрузки должен быть преобразуем к типу константы, представленному её описателем типа поля. Например, если динамическая константа имеет описатель типа поля "C" (char) то возвращаемый тип метода загрузки может быть Object, Character, или char, но не int или Integer.

Since:
1.7
Пакет Описание
java.lang
Предоставляет классы, являющиеся фундаментальными для разработки языка программирования Java.
Класс Описание
CallSite
CallSite — это контейнер для переменной MethodHandle, которая называется его target.
ConstantBootstraps
Методы загрузки для динамически вычисляемых констант.
ConstantCallSite
ConstantCallSite — это CallSite, целевой объект которого является постоянным и никогда не может быть изменён.
LambdaConversionException
LambdaConversionException
LambdaMetafactory
Методы для облегчения создания простых "объектов функций", которые реализуют один или несколько интерфейсов путём делегирования предоставленному MethodHandle, возможно после адаптации типов и частичной оценки аргументов.
MethodHandle
Обработчик метода — это типизированная, непосредственно исполняемая ссылка на базовую функцию, конструктор, поле или аналогичную низкоуровневую операцию, с необязательными преобразованиями аргументов или возвращаемых значений.
MethodHandleInfo
Символическая ссылка, полученная путём разбиения прямого обработчика метода на составляющие символические части.
MethodHandleProxies
Этот класс состоит исключительно из статических методов, которые помогают адаптировать обработчики методов к другим типам JVM, таким как интерфейсы.
MethodHandles
Этот класс состоит исключительно из статических методов, которые работают с обработчиками методов или возвращают их.
MethodHandles.Lookup
Объект поиска — это фабрика для создания обработчиков методов, когда создание требует проверки доступа.
MethodHandles.Lookup.ClassOption
Набор опций класса, определяющих, добавляется ли скрытый класс, созданный методом Lookup::defineHiddenClass, динамически в качестве нового члена к вложенному классу поиска и/или имеет ли скрытый класс сильную связь с загрузчиком классов, помеченным как его определяющий загрузчик.
MethodType
Тип метода представляет аргументы и возвращаемый тип, принимаемые и возвращаемые обработчиком метода, или аргументы и возвращаемый тип, передаваемые и ожидаемые вызывающей стороной обработчика метода.
MutableCallSite
MutableCallSite — это CallSite, переменная целевого объекта которого ведёт себя как обычное поле.
SerializedLambda
Сериализованная форма лямбда-выражения.
StringConcatException
StringConcatException выбрасывается StringConcatFactory при нарушении связующих инвариантов.
StringConcatFactory
Методы для облегчения создания методов конкатенации строк, которые могут использоваться для эффективной конкатенации известного числа аргументов известных типов, возможно после адаптации типов и частичной оценки аргументов.
SwitchPoint
SwitchPoint — это объект, который может публиковать переходы состояния другим потокам.
TypeDescriptor
Сущность, имеющая описатель типа.
TypeDescriptor.OfField<F extends TypeDescriptor.OfField<F>>
Сущность, имеющая описатель типа поля.
TypeDescriptor.OfMethod<F extends TypeDescriptor.OfField<F>,M extends TypeDescriptor.OfMethod<F,M>>
Сущность, имеющая описатель типа метода. Описатели методов, соответствующие JVMS 4.3.3, могут быть описаны номинально с помощью MethodType::describeConstable; в противном случае они не могут быть описаны номинально.
VarHandle
VarHandle — это динамически строго типизированная ссылка на переменную или на параметрически определённую семью переменных, включая статические поля, нестатические поля, элементы массивов или компоненты вне-кучной структуры данных.
VarHandle.AccessMode
Набор режимов доступа, которые определяют способ доступа к переменной, на которую ссылается VarHandle.
VarHandle.VarHandleDesc
Номинальный описатель для константы VarHandle.
VolatileCallSite
VolatileCallSite — это CallSite, целевой объект которого ведёт себя как переменная volatile.
WrongMethodTypeException
Выбрасывается для указания на то, что код попытался вызвать обработчик метода с неправильным типом метода.

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

Spec-Zone.ru

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