Как исправить UnsatisfiedLinkError (не удается найти зависимые библиотеки) в проекте JNI
Я работаю над проектом Java, который использует JNI. JNI вызывает собственную библиотеку, которую я написал сам, скажем, mylib.dll, и это зависит от сторонней библиотеки libsndfile-1.dll.
Когда я запускаю свою программу, он сбрасывается с помощью
java.lang.UnsatisfiedLinkError: C:\...path...\mylib.dll: Can't find dependent libraries.
Я искал этот сайт (и другие), и я пробовал ряд исправлений:
-
Я запустил ходячий ходячий. DW дал пару предупреждений: две библиотеки, требуемые libsndfile, MPR.DLL и SHLWAPI.DLL, имели "неразрешенные импорт", но DW FAQ сказал, что эти предупреждения можно смело игнорировать.
-
Я исправил имена методов в mylib.dll, как предложено здесь. Названия методов каким-то образом были искалечены компилятором, но я добавил флаги компоновщика, и имена методов dll теперь точно соответствуют тем, которые содержатся в моем jni файле заголовка.
-
Я поместил все эти DLL в тот же каталог - тот же каталог, что и .jar, который их вызывает, - чтобы убедиться, что они находятся в правой части PATH.
Нет кубиков.
Кто-нибудь знает, что происходит?
Я делаю свое развитие в Visual Studio 2010 на MacBook pro (через Parallels). Я делаю свое тестирование в Windows XP на ноутбуке toshiba.
Ответы
Ответ 1
Я уверен, что путь к классам и путь поиска разделяемой библиотеки имеют мало общего с друг другом. Согласно JNI Book (который, по общему признанию, старый), в Windows, если вы не используете системное свойство java.library.path
, DLL должна быть в текущем рабочем каталоге или в каталоге, указанном в переменной среды Windows PATH
.
Update:
Похоже, что Oracle удалил PDF со своего веб-сайта. Я обновил ссылку выше, чтобы указать на экземпляр PDF, который живет в Техасском университете - Арлингтон.
Кроме того, вы также можете прочитать версию Oracle HTML Спецификация JNI. Это живет в разделе Java 8 на веб-сайте Java и, надеюсь, будет некоторое время.
Обновление 2:
По крайней мере, в Java 8 (я не проверял более ранние версии) вы можете:
java -XshowSettings:properties -version
чтобы найти путь поиска совместно используемой библиотеки. Посмотрите на значение свойства java.library.path
в этом выпуске.
Ответ 2
Я хочу сообщить об этом интересном случае, после того, как перепробовал весь вышеописанный метод, ошибка все еще существует. Странная вещь, это работает на компьютере с Windows 7, но на Windows XP это не так. Затем я использую средство обхода зависимостей и обнаружил, что в Windows XP нет времени выполнения VC++ как моего требования к dll. После установки пакета VC++ Runtime здесь он работает как шарм. Что меня беспокоило, так это то, что он говорит "Не могу найти зависимые библиотеки", хотя интуитивно существует зависимая от JNI библиотека DLL, однако в конечном итоге выясняется, что зависимая библиотека JNI требует другого зависимого библиотеки DLL. Надеюсь, это поможет.
Ответ 3
Вам нужно загрузить библиотеку JNI.
System.loadLibrary загружает DLL из пути JVM (путь бина JDK).
Если вы хотите загрузить явный файл с путем, используйте System.load()
Смотрите также: Разница между System.load() и System.loadLibrary в Java
Ответ 4
Проверьте правильность пути к вашей библиотеке или нет. Конечно, вы можете использовать следующий код для проверки пути к пути к библиотеке:
System.out.println(System.getProperty("java.library.path"));
При запуске приложения Java вы можете назначить java.library.path:
java -Djava.library.path=path ...
Ответ 5
У вас была идентичная проблема с машиной XP при установке javacv
и opencv
в сочетании с Eclipse. Оказалось, что мне не хватает следующих файлов:
- msvcp100.dll
- msvcr100.dll
Как только они были установлены, проект скомпилирован и работает нормально.
Ответ 6
Если вы загружаете 32-разрядную версию вашей DLL с 64-разрядной JRE, у вас может возникнуть проблема. Это был мой случай.
Ответ 7
- Короткий ответ: для ошибки "невозможно найти зависимую библиотеку", проверьте свой $PATH (соответствует пункту № 3 пули ниже)
- Длинный ответ:
- Pure java world: jvm использует "Classpath" для поиска файлов классов.
- Мир JNI (java/родная граница): jvm использует "java.library.path" (который по умолчанию равен $PATH) для поиска dlls
- чистый родной мир: собственный код использует $PATH для загрузки других dll
Ответ 8
Я нашел отличную статью от друзей на keepafe, в которой рассказывалось то же, что и я. Это сработало для меня, так что, надеюсь, это поможет вам! Прочитайте, если вам интересно (Опасность загрузки собственных библиотек на Android) или просто используйте
compile 'com.getkeepsafe.relinker:relinker:1.2.3'
и заменить
System.loadLibrary("myLibrary");
с
ReLinker.loadLibrary(context, "mylibrary");
Ответ 9
У меня была точно такая же проблема, и, наконец, она была решена.
Я поместил все зависимые DLL в ту же папку, где был сохранен mylib.dll, и убедитесь, что JAVA Compiler смог его найти (если в пути компиляции нет mylib.dll, будет ошибка, сообщающая об этом во время компиляции). Важно отметить, что вы должны убедиться, что все зависимые библиотеки имеют одну и ту же версию с mylib.dll, например, если ваша версия mylib.dll является версией, тогда вы также должны поместить в нее версию всех зависимых библиотек,
Надеюсь, это поможет другим, кто столкнулся с одной и той же проблемой.
Ответ 10
У меня была такая же проблема, и я пробовал все, что было опубликовано здесь, чтобы исправить это, но никто не работал у меня.
В моем случае я использую Cygwin для компиляции dll. Кажется, что JVM пытается найти JRE DLL на виртуальном пути Cygwin.
Я добавил путь виртуального каталога Cygwin к DLL JRE, и теперь он работает.
Я сделал что-то вроде:
SET PATH = "/cygdrive/c/Program Files/Java/jdk1.8.0_45";% PATH%
Ответ 11
В моей ситуации я пытался запустить веб-сервис java в Tomcat 7 через разъем в Eclipse. Приложение работает хорошо, когда я развернул файл войны на экземпляр Tomcat 7 на моем ноутбуке. Для приложения требуется драйвер jdbc типа 2 для "IBM DB2 9.5". По какой-то нечетной причине соединитель в Eclispe не мог видеть или использовать пути в переменных среды IBM DB2, чтобы добраться до DLL файлов, установленных на моем ноутбуке, как клиент jcc. В сообщении об ошибке либо указано, что ему не удалось найти файл db2jcct2 dll, либо ему не удалось найти зависимые библиотеки для этого DLL файла. В конечном итоге я удалил соединитель и перестроил его. Затем он работал правильно. Я добавляю это решение здесь как документацию, потому что мне не удалось найти это конкретное решение в другом месте.
Ответ 12
Создание статической библиотеки работало для меня, компиляция с использованием g++ -static
. Он связывает зависимые библиотеки вместе со сборкой.
Ответ 13
- Перейдите в http://tess4j.sourceforge.net/usage.html и нажмите
Visual C++ Redistributable for VS2012
- Загрузите его и запустите
VSU_4\vcredist_x64.exe
или VSU_4\vcredist_x84.exe
в зависимости от конфигурации вашей системы.
- Поместите ваши файлы
dll
в папку lib
вместе с вашими другими библиотеками (например, \lib\win32-x86\your dll files
).