2016-10-03 5 views
0

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

Мой 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.

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

Любые идеи?

+2

Является ли определение JNI_OnLoad_kdu_1jni завернутым в 'extern 'C" '? Единственное, что я хотел бы предложить, - это назвать библиотеку чем-то простым, например «L.a». –

+0

Вы не можете загружать статически скомпилированные библиотеки. Вы должны связать их с .so или .dll. Ваш вопрос не имеет смысла. – EJP

+0

@EJP Java8 теперь поддерживает загрузку статических библиотек. Я собирался перекликать с комментарием вроде твоего, но JEP 178 меняет ситуацию. –

ответ

2

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

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

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

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

+0

Так что я думаю, что я застрял в компиляции динамической библиотеки для платформ с разными версиями glibc. Это, вероятно, проще, чем компиляция одного исполняемого файла с включенным JVM. – ksclarke

+1

Вы можете статически связать ваш предпочтительный glibc в динамической библиотеке вместо нее, используя динамическую. – EJP

+0

Спасибо, я здесь на новой территории. Я буду исследовать в этом направлении, если это возможно. – ksclarke

0

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

--- Оригинальное сообщение следующим образом ---

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

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

JNI_OnLoad_libname must return a value of JNI_VERSION_1_8 or higher. 

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

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

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

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

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

Also the notes in the enhancement echo this sentiment

The source code for the loader is helpful

Я бы запустить Java при отладке (GDB) и поставить точку останова в на Java_java_lang_ClassLoader_00024NativeLibrary_findBuiltinLib. Вы правы, примеров не так много.

+0

* «Статически связанный с JVM» * не совпадает с «статически скомпилированной библиотекой». – EJP

+0

@EJP Спасибо за указание. Я замалчивал это и да, кажется, что вы пытаетесь динамически загружать статическую библиотеку, когда на самом деле она не поддерживается. –

Смежные вопросы