Загрузка статически скомпилированной библиотеки в 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
, Вы правы, хороших примеров не так много.