Spec-Zone.ru › OpenJDK 21

Пакет java.lang.foreign

package java.lang.foreign

Предоставляет низкоуровневый доступ к памяти и функциям за пределами среды выполнения Java.

Доступ к внешней памяти

Основной абстракцией, используемой для доступа к внешней памяти, является MemorySegmentПРЕВЬЮ, представляющая собой непрерывный участок памяти, расположенный как внутри, так и вне кучи Java. Обычно сегменты памяти выделяются с использованием ArenaПРЕВЬЮ, которое управляет жизненным циклом областей памяти, поддерживающих выделенные им сегменты. Содержимое сегмента памяти описывается с помощью memory layoutПРЕВЬЮ, предоставляющего базовые операции для запроса размеров, смещений и ограничений выравнивания. Макеты памяти также предоставляют альтернативный, более абстрактный способ доступа к сегментам памяти доступа к сегментам памяти с использованием обработчиков переменныхПРЕВЬЮ, которые могут быть вычислены с помощью путей макета. Например, чтобы выделить внекучную область памяти, достаточно большой для хранения 10 значений примитивного типа int, и заполнить её значениями от 0 до 9, можно использовать следующий код:

try (Arena arena = Arena.ofConfined()) {
    MemorySegment segment = arena.allocate(10 * 4);
    for (int i = 0 ; i < 10 ; i++) {
        segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
    }
}
Этот код создаёт внешний сегмент памяти, то есть сегмент памяти, поддерживаемый внекучной памятью; размер сегмента составляет 40 байт, достаточно для хранения 10 значений примитивного типа int. Внешний сегмент выделяется с использованием ограниченной областиПРЕВЬЮ. Таким образом, доступ к внешнему сегменту ограничен текущей нитью (той, которая создала область). Более того, при закрытии области внешний сегмент становится недействительным, а поддерживающая его область памяти освобождается. Обратите внимание на использование конструкции try-with-resources: этот идиом гарантирует, что область внекучной памяти, поддерживающая внешний сегмент, будет освобождена в конце блока в соответствии с семантикой, описанной в разделе 14.20.3 спецификации языка Java.

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

Кроме того, чтобы предотвратить доступ к области памяти после её освобождения (т. е. использование после освобождения), сегмент также проверяется (при доступе), чтобы убедиться, что область, из которой он был получен, не была закрыта. Мы называем эту гарантию временной безопасностью.

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

Доступ к внешним функциям

Основными абстракциями, используемыми для доступа к внешним функциям, являются SymbolLookupПРЕВЬЮ, FunctionDescriptorПРЕВЬЮ и LinkerПРЕВЬЮ. Первая используется для поиска символов внутри библиотек; вторая используется для моделирования сигнатуры внешних функций, а третья используется для связывания внешних функций в качестве экземпляров MethodHandle, чтобы клиенты могли выполнять вызовы внешних функций непосредственно в Java, без необходимости промежуточных слоёв кода C/C++ (как это происходит с Java Native Interface (JNI)).

Например, чтобы вычислить длину строки с использованием стандартной функции C-библиотеки strlen на платформе Linux/x64, можно использовать следующий код:

 Linker linker = Linker.nativeLinker();
 SymbolLookup stdlib = linker.defaultLookup();
 MethodHandle strlen = linker.downcallHandle(
     stdlib.find("strlen").orElseThrow(),
     FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
 );

 try (Arena arena = Arena.ofConfined()) {
     MemorySegment cString = arena.allocateUtf8String("Hello");
     long len = (long)strlen.invokeExact(cString); // 5
 }
Здесь мы получаем родной компоновщикПРЕВЬЮ и используем его для поискаПРЕВЬЮ функции strlen в стандартной C-библиотеке; далее мы получаем получаемПРЕВЬЮ обработчик вызова вниз, нацеленный на данную функцию. Для успешного связывания мы должны предоставить экземпляр FunctionDescriptorПРЕВЬЮ, описывающий сигнатуру функции strlen. На основании этой информации компоновщик однозначно определит последовательность шагов, которые превратят вызов обработчика метода (здесь выполняемый с помощью MethodHandle.invokeExact(java.lang.Object...)) в вызов внешней функции в соответствии с правилами, определёнными ABI базовой платформы. Класс ArenaПРЕВЬЮ также предоставляет множество полезных методов для взаимодействия с внешним кодом, таких как преобразованиеПРЕВЬЮ строк Java в нуль-терминированные строки UTF-8, как показано в вышеприведённом примере.

Ограниченные методы

Некоторые методы в этом пакете считаются ограниченными. Ограниченные методы обычно используются для привязки данных и/или функций внешнего кода к элементам первого класса Java API, которые затем могут быть использованы клиентами напрямую. Например, ограниченный метод MemorySegment.reinterpret(long)ПРЕВЬЮ может использоваться для создания нового сегмента с тем же адресом и временными границами, но с заданным размером. Это может быть полезно для изменения размера сегментов памяти, полученных при взаимодействии с внешними функциями.

Привязка внешних данных и/или функций обычно небезопасна и, при неправильном выполнении, может привести к сбою JVM или к повреждению памяти при обращении к связанному элементу Java API. Например, неправильное изменение размера сегмента внешней памяти с помощью MemorySegment.reinterpret(long)ПРЕВЬЮ может привести к сбою JVM или, что ещё хуже, к неявной порче памяти при попытке доступа к изменённому сегменту. По этим причинам крайне важно, чтобы код, вызывающий ограниченный метод, никогда не передавал аргументы, которые могут привести к неправильной привязке внешних данных и/или функций к API Java.

Учитывая потенциальную опасность ограниченных методов, среда выполнения Java выводит предупреждение в поток стандартной ошибки каждый раз, когда вызывается ограниченный метод. Такие предупреждения можно отключить, предоставив доступ к ограниченным методам выбранным модулям. Это можно сделать либо с помощью специфичных для реализации командных строк, либо программно, например, вызвав ModuleLayer.Controller.enableNativeAccess(java.lang.Module)ПРЕВЬЮ.

Для каждого класса в этом пакете, если не указано иное, все аргументы методов ссылочного типа не должны быть null, и любой null аргумент вызовет NullPointerException. Этот факт не документируется отдельно для методов этого API.

Примечание API:
Обычные гарантии модели памяти, например, указанные в 6.6 и 10.4, не применяются при доступе к внешним сегментам памяти, поскольку эти сегменты поддерживаются областями внекучной памяти.
Примечание реализации:
В эталонной реализации доступ к ограниченным методам может быть предоставлен определённым модулям с использованием командной строки --enable-native-access=M1,M2, ... Mn, где M1, M2, ... Mn — имена модулей (для безымянного модуля можно использовать специальное значение ALL-UNNAMED). Если этот параметр указан, доступ к ограниченным методам предоставляется только перечисленным модулям. Если этот параметр не указан, доступ к ограниченным методам разрешён для всех модулей, но доступ к ограниченным методам будет выводить предупреждения во время выполнения.
Внешние спецификации
  • Спецификация Java Native Interface
Пакет Описание
java.lang
Предоставляет классы, фундаментальные для разработки на языке Java.
Класс Описание
AddressLayoutПРЕВЬЮ
Предварительный просмотр.
Макет значения, используемый для моделирования адреса некоторого участка памяти.
ArenaПРЕВЬЮ
Предварительный просмотр.
Арена управляет жизненным циклом сегментов нативной памяти, обеспечивая как гибкое выделение, так и своевременное освобождение.
FunctionDescriptorПРЕВЬЮ
Предварительный просмотр.
Дескриптор функции моделирует сигнатуру внешней функции.
GroupLayoutПРЕВЬЮ
Предварительный просмотр.
Составной макет, являющийся агрегацией нескольких разнородных макетов членов.
LinkerПРЕВЬЮ
Предварительный просмотр.
Ссылка предоставляет доступ к внешним функциям из кода Java и к коду Java из внешних функций.
Linker.OptionПРЕВЬЮ
Предварительный просмотр.
Опция ссылки используется для предоставления дополнительных параметров запросу связи.
MemoryLayoutПРЕВЬЮ
Предварительный просмотр.
Макет памяти описывает содержимое сегмента памяти.
MemoryLayout.PathElementПРЕВЬЮ
Предварительный просмотр.
Элемент в пути макета.
MemorySegmentПРЕВЬЮ
Предварительный просмотр.
Сегмент памяти предоставляет доступ к непрерывному участку памяти.
MemorySegment.ScopeПРЕВЬЮ
Предварительный просмотр.
Область моделирует жизненный цикл всех сегментов памяти, связанных с ней.
PaddingLayoutПРЕВЬЮ
Предварительный просмотр.
Макет заполнения.
SegmentAllocatorПРЕВЬЮ
Предварительный просмотр.
Объект, который может использоваться для выделения сегментов памятиПРЕВЬЮ.
SequenceLayoutПРЕВЬЮ
Предварительный просмотр.
Составной макет, обозначающий однородное повторение заданного макета элемента.
StructLayoutПРЕВЬЮ
Предварительный просмотр.
Макет группы, члены которого расположены друг за другом.
SymbolLookupПРЕВЬЮ
Предварительный просмотр.
Поиск символов извлекает адрес символа в одной или нескольких библиотеках.
UnionLayoutПРЕВЬЮ
Предварительный просмотр.
Макет группы, члены которой расположены в одном начальном смещении.
ValueLayoutПРЕВЬЮ
Предварительный просмотр.
Макет, моделирующий значения основных типов данных.
ValueLayout.OfBooleanПРЕВЬЮ
Предварительный просмотр.
Макет значения, носитель которого boolean.class.
ValueLayout.OfByteПРЕВЬЮ
Предварительный просмотр.
Макет значения, носитель которого byte.class.
ValueLayout.OfCharПРЕВЬЮ
Предварительный просмотр.
Макет значения, носитель которого char.class.
ValueLayout.OfDoubleПРЕВЬЮ
Предварительный просмотр.
Макет значения, носитель которого double.class.
ValueLayout.OfFloatПРЕВЬЮ
Предварительный просмотр.
Макет значения, носитель которого float.class.
ValueLayout.OfIntПРЕВЬЮ
Предварительный просмотр.
Макет значения, носитель которого int.class.
ValueLayout.OfLongПРЕВЬЮ
Предварительный просмотр.
Макет значения, носитель которого long.class.
ValueLayout.OfShortПРЕВЬЮ
Предварительный просмотр.
Макет значения, носитель которого short.class.

© 1993, 2023, 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/21/docs/api/java.base/java/lang/foreign/package-summary.html

Spec-Zone.ru

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