Загрузка статически скомпилированной библиотеки в Java

У меня возникают проблемы при загрузке статически скомпилированной библиотеки из Java с использованием System.loadLibrary(""), но я могу загрузить ее как динамически скомпилированную библиотеку (когда я ее так строю). Я использую JDK 8, и я понимаю, что он может загружать статические библиотеки через System.loadLibrary(""), если вы предоставляете JNI_OnLoad_L в файлах *.cpp и *.h.

Мой kdu_jni.h имеет:

extern "C"
JNIEXPORT jint JNICALL JNI_OnLoad_kdu_1jni(JavaVM *, void *);

Мой kdu_jni.cpp имеет:

JNIEXPORT jint JNICALL JNI_OnLoad_kdu_1jni(JavaVM *vm, void *reserved)
{
  return JNI_VERSION_1_8;
}

У меня есть файл libkdu_jni.a в моем каталоге java.library.path, когда я пытаюсь запустить скомпилированную версию. Он работает нормально с файлом libkdu_jni.so в том же каталоге, когда я пытаюсь загрузить его динамически. При попытке со статическим файлом (libkdu_jni.a) я получаю:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no kdu_jni in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)

Я вынул файл.so, прежде чем пытаться загрузить файл.a.

Я не уверен, что я делаю неправильно. Я не думаю, что он даже видит JNI_OnLoad_kdu_1jni() файла libkdu_jni.a, потому что я помещаю туда исключение, и я не вижу, как его выбрасывают. Я пробовал несколько итераций для этого имени: JNI_OnLoad_kdu_jni(), JNI_OnLoad_kdu_1jni(), JNI_OnLoad() и т. Д.

Есть идеи?

2 ответа

Решение

Насколько я понимаю, он может загружать статические библиотеки через System.loadLibrary(""), если вы предоставите JNI_OnLoad_L в файлах *.cpp и *.h.

Ваше понимание неверно. Вы не можете загрузить .a файл динамически. Это не выполнимо ни в какой форме или форме:

  • Инфра-библиотеки ссылки не разрешены
  • Ссылки вне библиотеки также не разрешаются: например, на библиотеку C.

Шаг связи важен, и JVM не делает это за вас. То, что вы прочитали, относится к библиотекам, статически связанным с JVM.

Я предлагаю вам попробовать JNI_OnLoad_kdu_jni как имя функции. Если это не сработает, оно может не работать с именами библиотек, которые содержат подчеркивание.

--- Оригинальный пост следует ---

До Java 8 поддерживались только библиотеки общих объектов.

Это означает, что для того, чтобы узнать, является ли статическая библиотека Java 8, в библиотеке должна быть реализована новая функция.

JNI_OnLoad_libname must return a value of JNI_VERSION_1_8 or higher.

Я полагаю, поскольку ваш код работает динамически, но не статически, возможно, этой функции нет. Часть JEP 178 ниже заставляет меня поверить в это:

Спецификации методов java.lang.System.loadLibrary и java.lang.Runtime.loadLibrary будут пересмотрены следующим образом:

Загружает собственную библиотеку, указанную аргументом libname. Имя библиотеки не должно содержать префикс, расширение файла или путь для конкретной платформы.

Если нативная библиотека с именем libname статически связана с ВМ, то вызывается функция JNI_OnLoad_libname, экспортированная библиотекой. Смотрите спецификацию JNI для более подробной информации.

В противном случае имя библиотеки загружается из расположения системной библиотеки и отображается в образ собственной библиотеки в зависимости от реализации.

Также примечания в улучшении повторяют это чувство

Исходный код для загрузчика полезен

Я запускаю Java в режиме отладки (gdb) и ставлю точку останова в Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib, Вы правы, хороших примеров не так много.

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