Связывание статической библиотеки с 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.

Ссылки:

Другие вопросы по тегам