2016-01-19 2 views
0

Я просто пытался создать игрушку для привязки собственного кода к Java только для удовольствия. Я успешно выполнил программу, используя программу System.load("/FULLPATH/mylib.so"), но при этом не удалось загрузить библиотеки с java.library.path, используя System.loadLibrary().Загрузка собственной библиотеки из java.library.path конкретно

Инструменты Я использую:

  • GCC 4.8.5 20150623 (Red Hat 4.8.5-4)
  • Java/Javac версии "1.8.0_66" (HotSpot 64 бит)
  • CentOS 7 (64 бит)

Последовательность сборки (такая же для обеих версий, упомянутых в первом абзаце).

 
rm TestIt.class mylib.so TestIt.h 
javac TestIt.java 
javah -stubs TestIt 
gcc -shared -I/$JDK8_HOME/include/ -I/$JDK8_HOME/include/linux/ -fPIC nativeTestItImpl.c -o mylib.so 

Java-код для загрузки библиотеки (просто статический инициализатор):

 
static { 
     System.out.println("System.getProperty(\"java.library.path\") is: " + System.getProperty("java.library.path")); 
     System.loadLibrary("mylib"); 
     //System.load("/FULLPATH/mylib.so");// ***This works*** 
    } 

Как я пытался установить путь к библиотеке:

 
java -Djava.library.path=/FULLPATH TestIt 
java -Djava.library.path=/FULLPATH/mylib.so TestIt 
java -Djava.library.path=. TestIt     #appeared as '.' 
java -Djava.library.path=/FULLPATH:$PATH TestIt 
#NOTE: DEFLT_LIB_PATH was the output of the above print statement when 
#  running "java TestIt" 
java -Djava.library.path=/FULLPATH:$DEFLT_LIB_PATH TestIt 
set LD_LIBRARY_PATH=/FULLPATH && java TestIt  ##did not appear in printout of lib 
export LD_LIBRARY_PATH=/FULLPATH && java TestIt ##preppended /FULLPATH: to DEFLT_LIB_PATH 

Все версии распечатаны в виде , ожидаемое исключение, помеченное надписью «##» выше.

Ошибка во всех случаях: Exception in thread "main" java.lang.UnsatisfiedLinkError: no mylib in java.library.path

Полный путь не имеет пробелы или специальные символы, так что я совершенно потерял, почему это так.

Также попробовали System.loadLibrary("mylib.so"); только для полноты.

ответ

1

Давайте посмотрим, что говорит Javadoc:

Грузы динамическая библиотека с указанным именем библиотеки. Файл, содержащий собственный код, загружается из локальной файловой системы из места, где обычно хранятся файлы библиотек. Детали этого процесса зависят от реализации. Отображение от имени библиотеки к определенному имени файла выполняется с учетом конкретной системы.

Поскольку вы используете CentOS 7, я сосредоточусь на Linux.

Проблема, с которой вы сталкиваетесь, заключается в том, что вы не следуете неписаному системному контракту для Linux. Что делает JVM для Linux, это преобразовать вызов в System.loadLibrary("foo") на звонок по номеру dlopen("libfoo.so"). Если вы переименуете свою библиотеку и исправьте аргумент, переданный в System.loadLibrary, он должен работать.

Мне не известно о «официальной» документации, в которой указывается этот контракт, но он, скорее всего, существует где-то.

Если вы хотите повеселиться, вы можете скачать OpenJDK и следовать цепочке вызовов.Вы должны в конечном итоге на этот кусок кода, определенного в hotspot/src/os/linux/vm/os_linux.cpp:

bool os::dll_build_name(char* buffer, size_t buflen, 
         const char* pname, const char* fname) { 
    bool retval = false; 
    // Copied from libhpi 
    const size_t pnamelen = pname ? strlen(pname) : 0; 

    // Return error on buffer overflow. 
    if (pnamelen + strlen(fname) + 10 > (size_t) buflen) { 
    return retval; 
    } 

    if (pnamelen == 0) { 
    snprintf(buffer, buflen, "lib%s.so", fname); 
    retval = true; 
    } else [...] 

os::dll_build_name используется, чтобы получить filename параметр, который передается в os::dll_load, который сам по себе вызывает dlopen(filename).

+0

О, поэтому я должен придерживаться соглашения об именах '' lib% s.so "' для использования этой функции. Спасибо, что отлично сработало после этого, спасибо. – SGM1

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