Связывание статической библиотеки с JNI
Версии Java до Java 8 требуют, чтобы нативный код находился в общей библиотеке, но я читал, что с Java 8 можно использовать статические связанные библиотеки с JNI. Я искал примеры, но не смог их найти.
Как я могу статически связать библиотеку JNI с моим Java-приложением?
2 ответа
Спецификация Java SE 8 была изменена для поддержки статического связывания, а статическое связывание реализовано в JDK. Это кратко упомянуто в спецификации System.loadLibrary. Разделы Спецификации JNI, на которые она ссылается, находятся здесь и здесь.
Собственные сигнатуры методов и типы данных одинаковы для статически и динамически связанных методов. Возможно, вам придется взломать make-файлы JDK, чтобы он статически связывал вашу библиотеку.
Одним существенным отличием является способ инициализации статических библиотек. Динамические библиотеки инициализируются путем вызова JNI_OnLoad
функции и деинициализируются путем вызова JNI_OnUnload
, Каждая динамическая библиотека может иметь свою версию этих функций. Если существует несколько статически связанных библиотек, очевидно, что они не могут иметь функции с одинаковыми именами. Для статической библиотеки с именем libname
функции загрузки / выгрузки JNI_OnLoad_libname
а также JNI_OnUnload_libname
,
JNI_OnLoad_libname
функция должна возвращать значение JNI_VERSION_1_8
или выше. Если этого не произойдет, JVM будет игнорировать статическую библиотеку.
В основном, если вы позвоните System.loadLibrary("foo")
система ищет функцию JNI_OnLoad_foo
в исполняемом исполняемом образе, и если он найден, предполагается, что библиотека статически связана, а ее собственные методы ищутся в работающем образе. Если JNI_OnLoad_foo
не найден, тогда происходит обычный поиск и загрузка динамических библиотек, и нативные методы связаны с динамической библиотекой, найденной таким образом.
Согласно JEP 178, на который вы ссылались в своем комментарии, вам не нужно ничего делать иначе. System.loadLibrary
теперь будет загружать как динамические, так и статические библиотеки.
Не требуется никаких изменений в существующем Java-коде, чтобы использовать статическую нативную библиотеку, а не динамическую нативную библиотеку. В частности, вызов метода в форме System.loadLibrary("foo") должен иметь возможность загружать библиотеку "foo" независимо от того, предоставляется ли эта библиотека в статической или динамической форме.
Возможно, вам просто нужно убедиться, что ваш java.library.path установлен правильно.
Расширение Java 8 https://openjdk.java.net/jeps/178 предназначено для JVM.
Учитывая два файла:
- Main.java
- Main.c
Создайте libnative.so:
javac Main.java
javah Main
gcc -c Main.c
gcc -c Main.c -I /home/dx/.sdkman/candidates/java/current/include/linux -I /home/dx/.sdkman/candidates/java/current/include
gcc -shared -o libnative.so Main.o
Создайте libnative.a:
ar -cvq libnative.a Main.o
Для каждого libnative.a тест libnative.so запускается через:
java -Djava.library.path=. Main
Результат:
- Успешное выполнение, когда
libnative.so
- Неудачное выполнение, когда
libnative.a
Это доказывает, что 178 для JVM.
Ссылки: