如何在JNI项目中修复UnsatisfiedLinkError(无法找到依赖库)

时间:2011-05-23 02:14:11

标签: java windows-xp java-native-interface libsndfile

我正在开发一个使用JNI的Java项目。 JNI调用我自己编写的自定义库,比如说mylib.dll,这取决于第三方库libsndfile-1.dll。

当我运行程序时,它会崩溃

java.lang.UnsatisfiedLinkError:  C:\...path...\mylib.dll: Can't find dependent libraries.

我搜索了这个网站(和其他网站),我尝试了很多修复:

  1. 我跑了依赖沃克。 DW给出了一些警告 - libsndfile,MPR.DLL和SHLWAPI.DLL所需的两个库具有“未解析的导入” - 但DW FAQ表示可以安全地忽略这些警告。

  2. 我按照建议here修复了mylib.dll中的方法名称。方法名称在某种程度上被编译器破坏了,但我添加了链接器标志,现在dll方法名称与我的jni头文件中的名称完全匹配。

  3. 我将所有这些DLL放在同一目录中 - 与调用它们的.jar相同的目录 - 以确保它们位于正确的路径上。

  4. 没有骰子。

    有谁知道发生了什么事?

    我正在使用MacBook pro(通过Parallels)在Visual Studio 2010中进行开发。我正在使用toshiba笔记本电脑在Windows XP中进行测试。

17 个答案:

答案 0 :(得分:43)

我很确定classpath和共享库搜索路径彼此之间几乎没有关系。根据{{​​3}}(不可否认是旧的),如果您不使用java.library.path系统属性,则在Windows上,DLL需要位于当前工作目录或Windows {{{1}中列出的目录中。 1}}环境变量。


<强>更新

看起来Oracle已从其网站上删除了PDF。我已经更新了上面的链接,指向生活在德克萨斯大学阿灵顿分校的PDF实例。

此外,您还可以阅读Oracle The JNI Book的HTML版本。它位于Java网站的Java 8部分,因此希望能够存在一段时间。


更新2:

至少在Java 8中(我没有检查过早期版本)你可以这样做:

PATH

找到共享库搜索路径。在该输出中查找java -XshowSettings:properties -version 属性的值。

答案 1 :(得分:17)

我想通知这个有趣的案例,在尝试了以上所有方法后,错误仍然存​​在。奇怪的是它适用于Windows 7计算机,但在Windows XP上则不然。然后我使用依赖walker,在Windows XP上找不到VC ++ Runtime作为我的dll要求。安装VC ++ Runtime包here后,它就像一个魅力。令我不安的是它一直在告诉无法找到依赖库,而直觉上JNI依赖的dll就在那里,但最终结果是JNI依赖的dll需要另一个依赖的dl。我希望这会有所帮助。

答案 2 :(得分:12)

您需要加载JNI库。

System.loadLibrary 从JVM路径(JDK bin路径)加载DLL。

如果您要加载带路径的显式文件,请使用 System.load ()

另请参阅:Difference between System.load() and System.loadLibrary in Java

答案 3 :(得分:4)

在将javacvopencv与Eclipse结合使用时,在XP机器上遇到了同样的问题。原来我错过了以下文件:

  • msvcp100.dll
  • msvcr100.dll

安装完成后,项目编译并运行正常。

答案 4 :(得分:4)

请验证您的图书馆路径是否正确。当然,您可以使用以下代码检查库路径路径: System.out.println(System.getProperty("java.library.path"));

启动Java应用程序时可以指定 java.library.path

java -Djava.library.path=path ...

答案 5 :(得分:3)

如果使用64位JRE加载32位版本的dll,则可能会遇到此问题。这是我的情况。

答案 6 :(得分:2)

我发现一些朋友在keepsafe上写了一篇很棒的文章,我做了同样的事情。它对我有用,所以希望它也可以帮到你!如果您有兴趣(The Perils of Loading Native Libraries on Android)或只是使用

,请阅读

ReLinker.loadLibrary(context, "mylibrary");

并替换

{{1}}

{{1}}

答案 7 :(得分:2)

  • 简答:对于“找不到依赖库”错误,请检查$ PATH(对应下面的项目符号#3)
  • 答案很长:
    1. 纯java世界:jvm使用“Classpath”查找类文件
    2. JNI world(java / native boundary):jvm使用“java.library.path”(默认为$ PATH)来查找dll
    3. 纯原生世界:本机代码使用$ PATH加载其他dll

答案 8 :(得分:1)

我曾经有过完全相同的问题,最后解决了。

我将所有依赖的DLL放入存储mylib.dll的同一文件夹中,并确保JAVA编译器可以找到它(如果编译路径中没有mylib.dll,则在编译期间会报告此错误)。您需要注意的重要事项是您必须确保所有依赖库与mylib.dll具有相同的版本,例如,如果您的mylib.dll是发行版,那么您还应该将其所有依赖库的发行版本放在那里。

希望这可以帮助遇到同样问题的其他人。

答案 9 :(得分:1)

在我的情况下,我试图通过Eclipse中的连接器在Tomcat 7中运行java Web服务。当我将war文件部署到笔记本电脑上的Tomcat 7实例时,应用程序运行良好。该应用程序需要一个jdbc类型2驱动程序用于&#34; IBM DB2 9.5&#34;。由于一些奇怪的原因,Eclispe中的连接器无法查看或使用IBM DB2环境变量中的路径,因此可以将我的笔记本电脑上安装的dll文件作为jcc客户端访问。该错误消息表明它找不到db2jcct2 dll文件,或者无法找到该dll文件的依赖库。最终,我删除了连接器并重建了它。然后它运作正常。我在这里添加此解决方案作为文档,因为我在其他地方找不到这个特定的解决方案。

答案 10 :(得分:1)

我有同样的问题,我尝试了发布在这里的所有内容来修复它,但没有一个对我有用。 在我的情况下,我正在使用Cygwin来编译dll。似乎JVM试图在虚拟Cygwin路径中找到JRE DLL。 我将Cygwin的虚拟目录路径添加到JRE的DLL中,现在可以正常工作了。 我做了类似的事情:

  

SET PATH =“/ cygdrive / c / Program Files / Java / jdk1.8.0_45”;%PATH%

答案 11 :(得分:0)

创建静态库对我来说很有效,使用g++ -static进行编译。它将依赖库与构建包捆绑在一起。

答案 12 :(得分:0)

安装Microsoft Visual C ++ 2010 SP1可再发行组件已修复

答案 13 :(得分:0)

将所需的dll放在文件夹中,并在PATH环境变量中设置文件夹路径。 确保反映了更新的环境PATH变量。

答案 14 :(得分:0)

将两个Android项目合并为一个项目后,我遇到了ffmpeg库的相同问题。

实际上是由于两个不同版本的ffmpeg库到达了,但是它们在内存中加载了相同的名称。一个库放在JNiLibs中,而另一个库放在另一个用作模块的库中。我无法修改模块代码,因为它是只读的,因此我将自己代码中使用的模块重命名为 ffmpegCamera ,并以相同的名称加载到内存中。

System.loadLibrary("ffmpegCamera");

这解决了该问题,现在两个版本的库都可以很好地加载,并且在内存中分别加载了名称和进程ID。

答案 15 :(得分:0)

调用System.loadLibrary()时,JVM将在java.library.path上查找您的本机库。但是,如果该本机库声明了对其他本机库的任何依赖关系,那么操作系统将承担查找那些本机库依赖项的任务。

由于操作系统没有java.library.path的概念,因此它将看不到放置在java.library.path上的任何目录。相反,它将仅在操作系统的PATH环境变量上搜索目录。如果本机库依赖项是操作系统本机库,则完全可以,因为它将在PATH上找到。但是,如果本机库依赖项是您或其他人创建的本机库,则除非将其放置在PATH上,否则将不会在PATH中找到它。此行为是奇怪的,出乎意料的,并且没有得到充分的记录,但是已在OpenJDK问题跟踪器here中进行了记录。您还可以找到另一个here来加强此说明的StackOverflow答案。

因此,您有两种选择。您可以使用System.loadLibrary()以正确的依赖关系顺序加载每个本机库,也可以修改PATH以包括存储本机库的目录。

答案 16 :(得分:-2)

  1. 转到http://tess4j.sourceforge.net/usage.html,然后点击Visual C++ Redistributable for VS2012
  2. 下载并运行VSU_4\vcredist_x64.exeVSU_4\vcredist_x84.exe,具体取决于您的系统配置
  3. dll文件放在lib文件夹中,以及其他库(例如\lib\win32-x86\your dll files)。