Как отладить ошибку java system.loadlibrary в Linux? - PullRequest
4 голосов
/ 18 июня 2009

У меня есть Java-программа, которая вызывает код C через JNI, который я пытаюсь запустить в Linux. Внешний код состоит из двух файлов .so: один для привязок JNI (созданный с помощью swig), а другой - с реальными функциями. У меня есть две библиотеки в одном каталоге, и LD_LIBRARY_PATH установлен правильно. ldd не сообщает о проблемах при запуске из командной строки, но когда я задаю для LD_LIBRARY_PATH то же значение в диалоговом окне «run configurations» в редакторе Eclipse и пытаюсь выполнить программу, появляется следующая ошибка:

java.lang.UnsatisfiedLinkError: [путь к библиотекам] / [библиотека привязок JNI] .so: [библиотека фактического кода] .so: не удается открыть общий объектный файл: такого файла или каталога нет

Это наводит меня на мысль, что библиотека-оболочка JNI успешно загружена, но происходит сбой, когда эта библиотека пытается загрузить библиотеку, содержащую фактический код. Есть ли способ отладить это дальше?

Далее я отмечу, что эта проблема возникает в самом редакторе eclipse и что я не пытался упаковать код в jar и запустить его в автономном экземпляре jvm.

Ответы [ 7 ]

2 голосов
/ 24 июня 2009

Я думаю, что проблема связана с вызовом System.loadLibrary (String) и использованием LD_LIBRARY_PATH. Использование loadLibrary ("foo") будет искать в вашем java.library.path что-то с именем libfoo.so. Если ничего не найдено с именем libfoo.so, вы получите эту ошибку.

Теперь, если вы просто настроили LD_LIBRARY_PATH, необходимые вам нативные символы будут автоматически подхвачены компоновщиком, поэтому вам не нужно настраивать -Djava.library.path.

По моему опыту работы с swig в проекте gdal, эта ошибка на самом деле безвредна, и поскольку LD_LIBRARY_PATH настроен, она будет работать нормально.

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

Когда я использую eclipse, я следую инструкциям, которые дал Daff, где вы редактируете нативную библиотеку под jar на вкладке Libraries в Build Path. Просто еще раз напомню, что это просто устанавливает java.library.path под обложки.

1 голос
/ 25 июня 2009

Возможно, вам просто нужно найти правильное место в диалоговом окне конфигурации запуска, чтобы включить параметр -Djava.library.path = .... Мне кажется, что вы хотите, чтобы -D определялся в «vm arguments» на вкладке аргументов, тогда как если вы хотите определить LD_LIBRARY_PATH, то это будет на вкладке среды. Затмение будет радостно позволять вам размещать вещи там, где они не будут иметь значения, что вы думаете, что они имеют в виду. Во всяком случае, я раньше использовал библиотеки таким образом, и если у меня будет возможность, я посмотрю, что сделал, и отредактирую свой ответ здесь.

Еще одна попытка - поиграть с LD_DEBUG. Вы можете установить переменную окружения LD_DEBUG на разные вещи (попробуйте ВСЕ), и тогда загрузчик linux расскажет все виды полезной информации о том, что приложение пытается загрузить, , где что-то ищет и т. Д. Конечно, это предполагает, что вы запускаете eclipse из командной строки, поэтому вы можете установить env vars и посмотреть диагностику загрузчика; но что касается системы, то когда вы запускаете свое приложение из затмения, оно просто выполняет затмение, поэтому любое поведение при загрузке библиотеки можно увидеть таким образом.

0 голосов
/ 20 ноября 2012

Добавление этого ответа может быть полезным. В машинах AIX нам нужно установить переменную среды LIBPATH вместо LD_LIBRARY_PATH.

0 голосов
/ 10 ноября 2010

Да, LD_LIBRARY_PATH работал для меня

0 голосов
/ 30 июня 2009

Существуют ли другие библиотеки, от которых зависят две ваши библиотеки? Если это так, вам нужно убедиться, что они также доступны для JVM.

Имейте в виду, что ручная настройка "-Djava.library.path", по-видимому, стирает путь к библиотеке по умолчанию.

То есть со следующим кодом:

public class LibTest {
    public static void main(String[] args) {
        String property = System.getProperty("java.library.path");
        StringTokenizer parser = new StringTokenizer(property, ":");
        while (parser.hasMoreTokens()) {
            System.err.println(parser.nextToken());
        }
    }
}

Запущен из затмения с выходами Java 1.6.0_14:

/opt/java/jre/lib/i386/client
/opt/java/jre/lib/i386
/opt/java/jre/../lib/i386
/opt/java/jre/lib/i386/client
/opt/java/jre/lib/i386
/usr/lib/xulrunner-devel-1.9.0.11
/usr/lib/xulrunner-devel-1.9.0.11
/usr/java/packages/lib/i386
/lib
/usr/lib

Но когда я устанавливаю аргумент JVM "-Djava.library.path = / tmp /", я получаю только:

/tmp/

Если вы вручную устанавливаете java.library.path, это может объяснить, почему ldd работает из командной строки, а ваш .so не из eclipse / java.

Вы можете попробовать не устанавливать java.library.path и использовать System.load с абсолютным путем к вашей библиотеке вместо вызова System.loadLibrary. Это может позволить JVM найти ваш .so и по-прежнему использовать путь по умолчанию при поиске его зависимостей.

Конечно, если это бесполезно, вы также можете попробовать включить вывод отладочной информации jni с помощью "-verbose: jni" в командной строке. Это может дать вам некоторые подсказки к проблеме.

0 голосов
/ 18 июня 2009

Насколько я знаю, Eclipse не использует LD_LIBRARY_PATH. Самый простой способ установить правильный путь к собственной библиотеке - это перейти к Свойства проекта -> Путь сборки Java -> Библиотеки Затем разверните запись в Системной библиотеке JRE или (если доступно) Jar-файл, который использует вашу нативную библиотеку, выберите «Native Library Location», затем нажмите «Edit ...» и выберите папку, в которой находятся ваши библиотеки. На самом деле она устанавливает переменную -Djava.library.path, поэтому вы должны включить ее в командную строку, если вы запускаете программу снаружи затмение.

0 голосов
/ 18 июня 2009

Вы можете попробовать -Djava.library.path=actual.so в параметрах командной строки, возможно?

В Windows у меня были похожие проблемы со сторонней библиотекой, которая использовала DLL-оболочку JNI для своих библиотек. В моем проекте была DLL в каталоге lib, поэтому я добавил lib в PATH (например, PATH=%PATH%;./lib переменная окружения, и все начало работать.

...