JEP 334: JVM Constants API
API для описания констант JVM
| Автор | Brian Goetz |
| Ответственный | Vicente Arturo Romero Zaldivar |
| Тип | Feature |
| Область | SE |
| Статус | Closed / Delivered |
| Выпуск | 12 |
| Компонент | core-libs / java.lang.invoke |
| Обсуждение | amber dash dev at openjdk dot java dot net |
| Блокирует | JEP 303: Intrinsics for the LDC and INVOKEDYNAMIC Instructions |
| Рецензенты | Alex Buckley |
| Одобрен | Brian Goetz |
| Создан | 2018/05/15 21:52 |
| Обновлён | 2022/08/02 15:54 |
| Задача | 8203252 |
Аннотация
Ввести API для моделирования номинальных описаний ключевых артефактов class-файлов и времени выполнения, в частности констант, которые можно загрузить из пула констант.
Мотивация
В каждом class-файле Java есть пул констант, в котором хранятся операнды инструкций байт-кода этого класса. В общих чертах записи пула констант описывают либо артефакты времени выполнения, такие как классы и методы, либо простые значения, такие как строки и целые числа. Все эти записи называются загружаемыми константами, потому что они могут служить операндами инструкции ldc («load constant», загрузка константы). Они также могут встречаться в списке статических аргументов bootstrap-метода для инструкции invokedynamic. При выполнении инструкции ldc или invokedynamic загружаемая константа разрешается в «живое» значение стандартного типа Java, например Class, String или int.
Программам, которые работают с файлами class, нужно моделировать инструкции байт-кода, а значит, и загружаемые константы. Однако стандартных типов Java для моделирования загружаемых констант недостаточно. Это может быть приемлемо для загружаемой константы, описывающей строку (запись CONSTANT_String_info), поскольку получить «живой» объект String несложно, но это проблематично для загружаемой константы, описывающей класс (запись CONSTANT_Class_info), поскольку получение «живого» объекта Class зависит от корректности и согласованности загрузки классов. К сожалению, загрузка классов во многом зависит от окружения и может завершиться неудачей по многим причинам: нужный класс не существует или может быть недоступен запрашивающей стороне; результат загрузки класса зависит от контекста; загрузка классов имеет побочные эффекты; а иногда загрузка класса может быть вообще невозможна (например, когда описываемые классы ещё не существуют или по другой причине не могут быть загружены, как при компиляции этих самых классов или при преобразовании во время jlink).
Поэтому программы, работающие с загружаемыми константами, были бы проще, если бы могли оперировать классами и методами, а также менее известными артефактами, такими как method handles (дескрипторы методов) и динамически вычисляемые константы, в чисто номинальной, символьной форме:
-
Библиотеки для разбора и генерации байт-кода должны описывать классы и method handles в символьной форме. Без стандартного механизма им приходится прибегать к самодельным решениям: к типам-дескрипторам, таким как
Handleв ASM, к кортежам строк (владелец метода, имя метода, дескриптор метода) или к самодельным (и подверженным ошибкам) кодировкам всего этого в одну строку. -
Bootstrap-методы для
invokedynamic, которые работают за счёт генерации байт-кода (например,LambdaMetafactory), были бы проще, если бы могли работать в символьной области, а не с «живыми» классами и method handles. -
Компиляторам и офлайн-преобразователям (например, плагинам
jlink) нужно описывать классы и члены классов, которые невозможно загрузить в работающую VM. Плагинам компилятора (например, процессорам аннотаций) точно так же нужно описывать элементы программы в символьных терминах.
Всем подобным библиотекам и инструментам пошёл бы на пользу единый стандартный способ описания загружаемых констант.
Описание
Мы определяем в новом пакете java.lang.invoke.constant семейство value-based типов символьных ссылок (JVMS 5.1), способных описать каждый вид загружаемых констант. Символьная ссылка описывает загружаемую константу в чисто номинальной форме, независимо от загрузки классов и контекста доступа. Некоторые классы могут сами выступать в роли своих символьных ссылок (например, String); для связываемых констант мы определяем семейство типов символьных ссылок (ClassDesc, MethodTypeDesc, MethodHandleDesc и DynamicConstantDesc), которые содержат номинальную информацию для описания этих констант.
Черновой снимок спецификации API можно найти здесь, а подробнее о его связи с возможностями из JEP 303 можно прочитать в этом сопроводительном документе.
Зависимости
Изначально этот JEP был частью JEP 303 (Intrinsics for the LDC and INVOKEDYNAMIC Instructions). Теперь JEP 303 зависит от этого JEP.