Пакет 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);
}
}
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.findOrThrow("strlen"),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
);
try (Arena arena = Arena.ofConfined()) {
MemorySegment cString = arena.allocateFrom("Hello");
long len = (long)strlen.invokeExact(cString); // 5
}
strlen в стандартной библиотеке C; затем получаемRESTRICTED дескриптор метода для вызова внешней функции, нацеленный на эту функцию. Для успешного завершения связывания необходимо предоставить экземпляр FunctionDescriptor, описывающий сигнатуру функции strlen. На основе этой информации компоновщик однозначно определит последовательность шагов, которая преобразует вызов дескриптора метода (в данном случае выполняемый с помощью MethodHandle.invokeExact(java.lang.Object...)) в вызов внешней функции согласно правилам ABI базовой платформы. Класс Arena также предоставляет множество полезных методов для взаимодействия с внешним кодом, например, преобразование строк Java в строки UTF-8 с нулевым завершающим символом, как показано в приведённом выше примере.
- Примечание к API:
- Обычные гарантии модели памяти (см. 17.4) не применяются при доступе к сегментам собственной памяти, поскольку эти сегменты основаны на областях памяти вне кучи.
- С версии:
- 22
- Внешние спецификации
| Класс | Описание |
|---|---|
| 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, 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://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/foreign/package-summary.html