Почему java.library.path не работает в Ubuntu?

Я работаю над java-компонентом, которому нужны некоторые библиотеки, т.е. .dll для системы Windows и .so файлы для системы Linux. Итак, я подготовил java-приложение в netbeans, добавил несколько зависимостей и построил проект.

Выполнение в Windows:

Когда я попытался запустить файл jar в системе Windows с помощью команды java -jar appName.jar, я получил java.lang.UnsatisfiedLinkError, поэтому я указал java.library.path во время выполнения, например java -Djava.library.path=full\\path\\to\\libs -jar appName.jar, и он успешно запустился в Windows.

Выполнение в Linux (ubuntu):

Когда я попытался выполнить тот же файл jar в Ubuntu с помощью той же команды java -Djava.library.path=/path/to/libs -jar appName.jar, я получил сообщение об ошибке, говорящее о том, что некоторые файлы .so не найдены в указанном месте (я проверил местоположение файла и права доступа, все в порядке)

Обновлено (добавлена ​​ошибка):

ubuntu@ubuntu-HP-dx2480-MT-KL969AV:~/Desktop$ java -Djava.library.path=/home/ubuntu/Desktop/bin -jar JavaApplication4.jar

инициализировать в потоке [AWT-EventQueue-0,6, main] с путем к библиотеке bin bin/jcef_helper: ошибка при загрузке общих библиотек: libcef.so: невозможно открыть общий объектный файл: нет такого файла или каталога

содержит папку bin

-rwxr-xr-x 1 ubuntu ubuntu   1483321 Jun 18  2014 cef.pak
-rwxr-xr-x 1 ubuntu ubuntu   3258231 Jun 18  2014 devtools_resources.pak
-rwxr-xr-x 1 ubuntu ubuntu    971264 Jun 11  2014 ffmpegsumo.dll
-rwxr-xr-x 1 ubuntu ubuntu   9994752 Jun 11  2014 icudt.dll
-rwxr-xr-x 1 ubuntu ubuntu    429568 Jun 18  2014 jcef.dll
-rwxr-xr-x 1 ubuntu ubuntu    481488 Jun 18  2014 jcef_helper
-rwxr-xr-x 1 ubuntu ubuntu    233984 Jun 18  2014 jcef_helper.exe
-rwxr-xr-x 1 ubuntu ubuntu  53280768 Jun 11  2014 libcef.dll
-rwxr-xr-x 1 ubuntu ubuntu 105317136 Jun 18  2014 libcef.so
-rwxr-xr-x 1 ubuntu ubuntu   1309288 Jun 18  2014 libffmpegsumo.so
-rwxr-xr-x 1 ubuntu ubuntu   1047296 Jun 18  2014 libjcef.so drwxrwxrwx 2 ubuntu ubuntu      4096 Dec 23 11:29 locales

Путем поиска я узнал, что пытался использовать переменную среды LD_LIBRARY_PATH, поэтому я создал файл sh с командой:

export LD_LIBRARY_PATH=/path/to/libs

java -jar /path/to/appName.jar  

и когда я запускаю файл sh, моя программа работает успешно.

Итак, мой вопрос: почему java.library.path не работает для Ubuntu (Linux)? Похоже, что java.library.path только для Windows?


person Amogh    schedule 23.12.2014    source источник
comment
-Djava.library.path=path/to/libs это опечатка или здесь используется относительный путь?   -  person PeterMmm    schedule 23.12.2014
comment
Извините, это опечатка, я использую полный путь, например C:\winlibs\ для Windows и \home\ubuntu\Desktop\Linuxlibs   -  person Amogh    schedule 23.12.2014
comment
Вы должны предоставить сообщение об ошибке здесь для лучшего ответа.   -  person secmask    schedule 23.12.2014
comment
@secmask, добавлена ​​рассматриваемая ошибка. Пожалуйста, найдите Обновлено (добавлена ​​ошибка):   -  person Amogh    schedule 23.12.2014
comment
Вы указываете /home/ubuntu/Desktop/bin, может быть, этим библиотекам нужны другие библиотеки, которых здесь нет? Помните, что java.library.path может содержать несколько путей.   -  person PeterMmm    schedule 23.12.2014
comment
@PeterMmm, но указание того же пути к LD_LIBRARY_PATH работает, как?   -  person Amogh    schedule 23.12.2014
comment
Ваш комментарий выше сбивает с толку: вы использовали \home\ubuntu\Desktop\Linuxlibs или /home/ubuntu/Desktop/Linuxlibs? В Linux в качестве разделителя файлов используется косая черта.   -  person bernardn    schedule 23.12.2014
comment
@bernardn, так что извините снова за опечатку, я использовал правильную косую черту :), еще раз извините.   -  person Amogh    schedule 23.12.2014
comment
Может ли это быть несоответствие 32/64-битной Java? Существует также переменная среды LD_LIBRARYN32_PATH.   -  person PeterMmm    schedule 23.12.2014
comment
@PeterMmm, я так не думаю. Потому что, согласно JCEF, бинарное распределение предоставляется только для 64-битной JVM, и я также использую 64-битную ОС с 64-битной JVM.   -  person Amogh    schedule 23.12.2014
comment
пожалуйста, предоставьте ls -l /home/ubuntu/Desktop/bin   -  person secmask    schedule 23.12.2014
comment
привет, вы можете использовать jarsplice для создания собственного приложения jar вот полезная ссылка jarsplice   -  person Bhargav Modi    schedule 23.12.2014
comment
Попробуйте эту команду LD_LIBRARY_PATH=/home/ubuntu/Desktop/bin java -Djava.library.path=/home/ubuntu/Desktop/bin -jar /jar/path.jar   -  person secmask    schedule 23.12.2014
comment
@secmask, но после использования LD_LIBRARY_PATH нет необходимости в Djava.library.path   -  person Amogh    schedule 23.12.2014
comment
о, просто чтобы убедиться, он основан на примере run.sh из двоичного пакета jcef.   -  person secmask    schedule 23.12.2014


Ответы (4)


Итак, мой вопрос: почему java.library.path не работает для Ubuntu (Linux)? Это как java.library.path только для окон?

Это работает, мы часто им пользуемся. Запустите приложение с помощью -XshowSettings:properties и посмотрите на путь поиска для отладки.

Обычно мы развертываем библиотеки в виде пакета для /usr/local/lib, так как библиотеки часто используются и другими компонентами. Не забудьте вызвать ldconfig после размещения туда новой библиотеки (так много для части export LD_LIBRARY_PATH).

Насколько я помню, должно быть достаточно просто добавить папку с -Djava.library.path, если я правильно помню. Я посмотрю на это и скажу вам позже, чтобы уточнить.

Также, пожалуйста, опубликуйте readlink -f /home/ubuntu/Desktop/bin, file /home/ubuntu/Desktop/bin/libcef.so и ldd /home/ubuntu/Desktop/bin/libcef.so.

Обновление: я попытаюсь объяснить, почему все работает, а почему нет.

Давайте поговорим о java.library.path. Это свойство используется виртуальной машиной для поиска библиотек. Взгляните на java.lang.System#load*( Строка libName) для справки. Свойство java.library.path имеет несколько предустановленных путей, следующее показывает вывод в моем поле ubuntu:

ortang@vbox-devel:~$ java -XshowSettings:properties
Property settings:
    ...
    java.library.path = /usr/java/packages/lib/amd64
        /usr/lib/x86_64-linux-gnu/jni
        /lib/x86_64-linux-gnu
        /usr/lib/x86_64-linux-gnu
        /usr/lib/jni
        /lib
        /usr/lib

Имейте в виду, что использование этого свойства заменит существующее свойство.

ortwin@vbox-devel:~$ java -Djava.library.path=/some/other/folder:/yet/another/one -XshowSettings:properties
Property settings:
    ...
    java.library.path = /some/other/folder
        /yet/another/one

Все идет нормально. JVM ищет только в папках, определенных в этом свойстве!

Библиотеки, которые вы загружаете в JVM, скорее всего, будут иметь зависимости от других библиотек. Имейте в виду, что эти зависимости просматриваются операционной системой, как и любая другая разделяемая библиотека!

Поэтому, чтобы решить вашу проблему, вы должны убедиться, что загруженные вами библиотеки имеют свои зависимости! Используйте ldd для отладки этого вопроса.

Переменная окружения LD_LIBRARY_PATH выполняет аналогичную работу, добавляя пути, которые будут использоваться операционной системой для поиска библиотек. Я не сторонник использования его в производственных средах.

person Ortwin Angermeier    schedule 23.12.2014
comment
да, копирование всех файлов с /home/ubuntu/Desktop/bin по /usr/local/lib сработало для команды java -Djava.library.path=/home/ubuntu/Desktop/bin -jar appName.jar. Это тоже без использования export LD_LIBRARY_PATH - person Amogh; 23.12.2014
comment
readlink -f /home/ubuntu/Desktop/bin дает /home/ubuntu/Desktop/bin - person Amogh; 23.12.2014
comment
file /home/ubuntu/Desktop/bin/libcef.so дает /home/ubuntu/Desktop/bin/libcef.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=0x2cba7c71da1e6000d154c84e3de947aa9380a2fd, not stripped - person Amogh; 23.12.2014
comment
Я попробовал file с jcef_helper, потому что в соответствии с ошибкой, которую я разместил в вопросе, файл libcef.so не найден при вводе jcef_helper file /home/ubuntu/Desktop/bin/jcef_helper, поэтому дает /home/ubuntu/Desktop/bin/jcef_helper: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x3cc71c45cf3d5d9e27f89cab9c5ea6b04165343a, not stripped - person Amogh; 23.12.2014
comment
для jcef_helper он говорит (uses shared libs), поэтому я попробовал ldd /home/ubuntu/Desktop/bin/jcef_helperв выводе он говорит libcef.so => not found, но после добавления файлов в /usr/local/lib путь к файлу разрешается. - person Amogh; 23.12.2014

Мое лучшее предположение для вашей проблемы заключается в том, что вы должны использовать как java.library.path и LD_LIBRARY_PATH. Действительно, j.l.p предназначен для java для загрузки вашей библиотеки JNI, а L_L_P для операционной системы для загрузки общей библиотеки и любых зависимых библиотек. Если ваша общая библиотека зависит от других библиотек по другим путям, вы должны указать эти пути.

person bernardn    schedule 23.12.2014
comment
О, так это то же самое, что настроить j.l.p для Windows, заботясь о загрузке библиотек с зависимой библиотекой, тогда как в настройке Linux только j.l.p загружает зависимую библиотеку, в моем случае это jcef_helper, но jcef_helper нужен файл libcef.so, который не загружается, поэтому нам нужно настроить L_L_P, который устанавливает переменную среды, и ОС позаботится о загрузке библиотеки и зависимой от нее библиотеки, поправьте меня, если я где-то ошибаюсь. - person Amogh; 23.12.2014
comment
Windows использует разные параметры для загрузки библиотек DLL, один из которых совпадает с путем загрузки библиотеки. Другой — это пути, перечисленные в переменной окружения PATH. - person bernardn; 23.12.2014
comment
Хорошо, я просто kalblogs.blogspot.in/2009/01/java.html эта статья, теперь понятно, почему j.l.p недостаточно для linux sys. Это похоже на то, что jcef_helper требуется libcef.so, но поскольку мы устанавливаем jlp, которая разрешает библиотеку (jcef_helper), но эта библиотека ссылается или динамически связана с другим файлом (libcef.so), который не загружается путем установки jlp, ХОТЯ ОБА ФАЙЛА НАХОДЯТСЯ В ОДНОМ КАТАЛЕ I.E /home/ ubuntu/Desktop/bin, где как L_L_P загружает все библиотеки со своими ссылочными или динамически связанными файлами. - person Amogh; 23.12.2014
comment
Ваше понимание кажется правильным. Итак, укажите L_L_P и j.l.p, и все должно работать. - person bernardn; 23.12.2014

кажется, что jcef не нашел своих зависимостей, попробуйте ldd libcef.so |grep "not found" и ldd libjcef.so |grep "not found" и исправьте недостающие библиотеки. На моей машине (ubuntu 14.04) отсутствует libudev.so.0 , моя машина имеет /lib/x86_64-linux-gnu/libudev.so.1, поэтому обманите ее с помощью ln -s /lib/x86_64-linux-gnu/libudev.so.1 /lib/x86_64-linux-gnu/libudev.so.0 и sudo ldconfig, чтобы перезагрузить кеш ld.

person secmask    schedule 23.12.2014
comment
для libudev я уже исправил. попробуйте ldd jcef_helper, он скажет, что libcef.so не найдено. по крайней мере в моем случае - person Amogh; 23.12.2014
comment
скопировав все файлы с /home/ubuntu/Desktop/bin по /usr/local/lib сработало для команды java -Djava.library.path=/home/ubuntu/Desktop/bin -jar appName.jar. Это тоже без использования экспорта LD_LIBRARY_PATH - person Amogh; 23.12.2014
comment
Пожалуйста, прочитайте ответ @OrtwinAngermeier и мои выводы в комментариях к тому же ответу. - person Amogh; 23.12.2014
comment
java загружает libjcef.so из своего кода, из сообщения об ошибке. Можно сказать, что java может видеть и загружать libjcef.so, но когда libjcef.so загружает libcef.so в качестве своей зависимости, возникает ошибка. Сказал, что не может найти libcef.so в пути поиска. Вы можете попробовать другой способ: создать файл /etc/ld.so.conf.d/cef.conf с содержимым /home/ubuntu/Desktop/bin, затем перезагрузить кеш ld с sudo ldconfig, а также проверить, что LD_LIBRARY_PATH работает на вашем компьютере как обычно. - person secmask; 23.12.2014
comment
Хорошо, постараюсь. но один вопрос все еще в моей голове, можно спросить? - person Amogh; 23.12.2014
comment
когда в Windows все библиотеки и ссылочные или общие библиотеки автоматически загружаются, когда они хранятся в одном каталоге, но в Linux это не делается, хотя и jcef_helper, и libcef.so хранятся в одном каталоге, как вы видите в ls -l. Обычно мы говорим, что хранение библиотек и связанных с ними библиотек в одной папке не создает никаких проблем. тогда почему я столкнулся с проблемой в Ubuntu? - person Amogh; 23.12.2014
comment
Это то, как они заставляют Linux работать, Linux по умолчанию не ищет общую библиотеку по тому же пути, что и исполняемый файл. Но вы можете включить исполняемый путь в путь поиска, используя rpath, см. readelf -d libjcef.so |grep runpath - person secmask; 23.12.2014

Я сталкиваюсь с той же проблемой, я использую -Djava.library.path, но это не работает. Я добавляю -Dsun.boot.library.path в качестве попытки, это работает!

пытаться:

java -Dsun.boot.library.path=/path/to/libs -jar appName.jar
person Lei Chu    schedule 18.05.2021
comment
Это что-то вроде взлома, если оно работает и, возможно, не связано с вопросом - sun.boot.library.path служит другой цели, чем java.library.path, поскольку первое предназначено для библиотек, связанных с самой JVM, а второе - для библиотек, связанных с вашим проектом. повторно давая ему бежать. - person RJGRawlings; 18.05.2021