Интерфейс SymbolLookup
- Функциональный интерфейс:
- Это функциональный интерфейс и поэтому может быть использован в качестве целевого назначения для лямбда-выражения или ссылки на метод.
@FunctionalInterface public interface SymbolLookup
SymbolLookup является предварительной API платформы Java. Поиск символа создаётся относительно конкретной библиотеки (или библиотек). После этого метод find(String) принимает имя символа и возвращает адрес символа в этой библиотеке.
Адрес символа моделируется как сегмент памяти нулевой длины memory segmentПРЕДПРОСМОТР. Сегмент может быть использован различными способами:
- Он может быть передан в
LinkerПРЕДПРОСМОТР для создания дескриптора метода вызова, который затем может использоваться для вызова внешней функции по адресу сегмента. - Он может быть передан существующему дескриптору метода вызоваПРЕДПРОСМОТР в качестве аргумента для подлежащей внешней функции.
- Он может быть сохранёнПРЕДПРОСМОТР внутри другого сегмента памяти.
- Он может быть использован для доступа к области памяти, поддерживающей глобальную переменную (для этого требуется изменение размераПРЕДПРОСМОТР сегмента предварительно).
Получение поиска символа
Методы-фабрикиlibraryLookup(String, Arena) и libraryLookup(Path, Arena) создают поиск символа для библиотеки, известной операционной системе. Библиотека задаётся либо её именем, либо путём. Библиотека загружается, если она ещё не загружена. Поиск символа, известный как поиск библиотеки, и его жизненный цикл контролируется объектом области памятиПРЕДПРОСМОТР. Например, если предоставленная область памяти является ограниченной областью памяти, библиотека, связанная с поиском символа, разгружается при закрытииПРЕДПРОСМОТР ограниченной области памяти: try (Arena arena = Arena.ofConfined()) {
SymbolLookup libGL = SymbolLookup.libraryLookup("libGL.so", arena); // libGL.so loaded here
MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
...
} // libGL.so unloaded here
Если библиотека была ранее загружена через JNI, т.е. с помощью System.load(String) или System.loadLibrary(String), то библиотека также была связана с определённым загрузчиком классов. Метод-фабрика loaderLookup() создаёт поиск символа для всех библиотек, связанных с загрузчиком классов вызывающего объекта:
System.loadLibrary("GL"); // libGL.so loaded here
...
SymbolLookup libGL = SymbolLookup.loaderLookup();
MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
Обратите внимание, что поиск загрузчика предоставляет символы только в библиотеках, которые ранее были загружены через JNI, т.е. с помощью System.load(String) или System.loadLibrary(String). Поиск загрузчика не предоставляет символы в библиотеках, которые были загружены во время создания поиска библиотеки:
libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
loaderLookup().find("glGetString").isPresent(); // false
L предоставляет символы в L даже если L была ранее загружена через JNI (связь с загрузчиком классов не имеет значения для поиска библиотеки): System.loadLibrary("GL"); // libGL.so loaded here
libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
Наконец, каждый LinkerПРЕДПРОСМОТР предоставляет поиск символа для библиотек, которые обычно используются на комбинации ОС и процессора, поддерживаемой этим LinkerПРЕДПРОСМОТР. Этот поиск символа, известный как поиск по умолчанию, помогает клиентам быстро находить адреса известных символов. Например, LinkerПРЕДПРОСМОТР для Linux/x64 может выбрать предоставление символов в libc через поиск по умолчанию:
Linker nativeLinker = Linker.nativeLinker();
SymbolLookup stdlib = nativeLinker.defaultLookup();
MemorySegment malloc = stdlib.find("malloc").orElseThrow();
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
Optional |
find |
Возвращает адрес символа с заданным именем. |
static SymbolLookupPREVIEW |
libraryLookup |
Загружает библиотеку с заданным именем (если она ещё не загружена) и создаёт поиск символа для символов в этой библиотеке. |
static SymbolLookupPREVIEW |
libraryLookup |
Загружает библиотеку из заданного пути (если она ещё не загружена) и создаёт поиск символа для символов в этой библиотеке. |
static SymbolLookupPREVIEW |
loaderLookup() |
Возвращает поиск символа для символов в библиотеках, связанных с загрузчиком классов вызывающего объекта. |
default SymbolLookupPREVIEW |
or |
Возвращает составной поиск символа, который возвращает результат поиска символа с этим поиском, если он найден, в противном случае возвращает результат поиска символа с другим поиском. |
Подробное описание методов
find
Optional<MemorySegmentPREVIEW> find(String name)
- Параметры:
-
name- имя символа. - Возвращает:
- сегмент памяти нулевой длины, адрес которого указывает на адрес символа, если он найден.
or
default SymbolLookupPREVIEW or(SymbolLookupPREVIEW other)
- Примечание API:
- Этот метод можно использовать для объединения нескольких поисков символов, например, чтобы символы могли быть извлечены, по порядку, из нескольких библиотек: Приведенный выше код создает поиск символов, который сначала ищет символы в библиотеке "foo". Если символ не найден в "foo", то ищется в "bar". Наконец, если символ не найден ни в "foo", ни в "bar", используется поиск загрузчика поиск загрузчика.
var lookup = SymbolLookup.libraryLookup("foo", arena) .or(SymbolLookup.libraryLookup("bar", arena)) .or(SymbolLookup.loaderLookup()); - Параметры:
-
other- поиск символов, который должен использоваться для поиска символов, не найденных в этом поиске. - Возвращает:
- составной поиск символов, который возвращает результат поиска символа с этим поиском, если найден, в противном случае возвращает результат поиска символа с другим поиском
loaderLookup
static SymbolLookupPREVIEW loaderLookup()
Библиотека связана с загрузчиком классов CL когда библиотека загружается с помощью вызова System.load(String) или System.loadLibrary(String) из кода в классе, определенном CL. Если этот код делает дальнейшие вызовы System.load(String) или System.loadLibrary(String), то загружаются и связываются дополнительные библиотеки с CL. Поиск символов, возвращаемый этим методом, всегда актуальный: он отражает все библиотеки, связанные с соответствующим загрузчиком классов, даже если они были загружены после возвращения этого метода.
Библиотеки, связанные с загрузчиком классов, разгружаются, когда загрузчик классов становится недоступным. Поиск символов, возвращаемый этим методом, связан со свежим объёмомОБЗОР, который сохраняет доступность загрузчика классов вызывающей стороны. Таким образом, библиотеки, связанные с загрузчиком классов вызывающей стороны, остаются загруженными (и их символы доступны) до тех пор, пока поиск загрузчика для этого загрузчика классов, или любой из сегментов, полученных им, доступен.
В случаях, когда этот метод вызывается из контекста, в котором нет фрейма вызова в стеке (например, при вызове непосредственно из потока, подключенного JNI), загрузчик классов вызывающей стороны по умолчанию устанавливается в системный загрузчик классов.
- Возвращает:
- поиск символов для символов в библиотеках, связанных с загрузчиком классов вызывающей стороны.
- См. также:
libraryLookup
static SymbolLookupPREVIEW libraryLookup(String name, ArenaPREVIEW arena)
Этот метод ограничен. Ограниченные методы небезопасны, и при неправильном использовании их использование может привести к сбою JVM или, что еще хуже, к молчаливому результату повреждения памяти. Таким образом, клиенты должны воздерживаться от зависимости от ограниченных методов и использовать безопасные и поддерживаемые функции, где это возможно.
- Примечание реализации:
- Процесс разрешения имени библиотеки зависит от ОС. Например, в POSIX-совместимой ОС имя библиотеки разрешается в соответствии со спецификацией функции
dlopenдля этой ОС. В Windows имя библиотеки разрешается в соответствии со спецификацией функцииLoadLibrary. - Параметры:
-
name- имя библиотеки, в которой должны быть просмотрены символы. -
arena- область, связанная с символами, полученными из возвращаемого поиска. - Возвращает:
- новый поиск символов, подходящий для поиска символов в библиотеке с заданным именем.
- Выбрасывает:
-
IllegalStateException- еслиarena.scope().isAlive() == false -
WrongThreadException- еслиarenaявляется ограниченной областью, и этот метод вызывается из потокаT, отличного от потока владельца области. -
IllegalArgumentException- еслиnameне определяет допустимую библиотеку. -
IllegalCallerException- Если вызывающий элемент находится в модуле, у которого не включен доступ к нативным функциям.
libraryLookup
static SymbolLookupPREVIEW libraryLookup(Path path, ArenaPREVIEW arena)
Этот метод ограничен. Ограниченные методы небезопасны, и при неправильном использовании их использование может привести к сбою JVM или, что еще хуже, к молчаливому результату повреждения памяти. Таким образом, клиенты должны воздерживаться от зависимости от ограниченных методов и использовать безопасные и поддерживаемые функции, где это возможно.
- Примечание реализации:
- В Linux функции, предоставляемые этим фабричным методом и возвращаемым поиском символов, реализованы с использованием функций
dlopen,dlsymиdlclose. - Параметры:
-
path- путь к библиотеке, в которой должны быть просмотрены символы. -
arena- область, связанная с символами, полученными из возвращаемого поиска. - Возвращает:
- новый поиск символов, подходящий для поиска символов в библиотеке с заданным путем.
- Выбрасывает:
-
IllegalStateException- еслиarena.scope().isAlive() == false -
WrongThreadException- еслиarenaявляется ограниченной областью, и этот метод вызывается из потокаT, отличного от потока владельца области. -
IllegalArgumentException- еслиpathне указывает на действительную библиотеку. -
IllegalCallerException- Если вызывающий элемент находится в модуле, у которого не включен доступ к нативным функциям.
© 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/SymbolLookup.html
SymbolLookupтолько при включённых предварительных функциях.