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

dB'*_*dB' 79 java java-native-interface windows-xp libsndfile

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

当我运行我的程序时,它崩溃了

java.lang.UnsatisfiedLinkError:  C:\...path...\mylib.dll: Can't find dependent libraries.
Run Code Online (Sandbox Code Playgroud)

我搜索了这个网站(和其他人),我尝试了一些修复:

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

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

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

没有骰子.

有谁知道发生了什么事?

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

Qua*_*nic 48

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


更新:

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

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


更新2:

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

java -XshowSettings:properties -version
Run Code Online (Sandbox Code Playgroud)

找到共享库搜索路径.java.library.path在该输出中查找属性的值.

  • @SL_User我想如果你将库所在的目录添加到环境变量"path"并重新启动命令提示符或终端,它应该修复它.Java在classpath下查找jar,在path下查找库. (5认同)
  • 是的,`CLASSPATH`根本就没用过.我也不确定`cwd`是否被使用过.`java.library.path`或只是`PATH`将起作用.@dB',你现在得到它们的地方是*错*. (2认同)

lon*_*kit 17

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

  • 在这种情况下,该消息是正确的,尽管有误导性.我在测试盒上缺少VC++运行时,并且在调试模式下编译库(取决于*non*-redistributable调试运行时).[Dependency Walker](http://www.dependencywalker.com/)对于解决这个问题非常有帮助. (4认同)

Yoc*_*mer 13

您需要加载JNI库.

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

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

另请参见:Java中的System.load()和System.loadLibrary之间的区别


EFa*_*lco 8

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


小智 6

在安装javacvopencv结合 Eclipse时,在 XP 机器上确实有相同的问题。结果发现我丢失了以下文件:

  • msvcp100.dll
  • msvcr100.dll

安装这些后,项目编译并运行正常。


cao*_*eng 5

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

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

java -Djava.library.path=path ...
Run Code Online (Sandbox Code Playgroud)


小智 5

当调用 时System.loadLibrary(),JVM 将查找java.library.path您的本机库。但是,如果该本机库声明了对其他本机库的任何依赖项,则操作系统将负责查找这些本机库依赖项。

由于操作系统没有 的概念java.library.path,因此它不会看到您放置在 java.library.path 上的任何目录。相反,它只会搜索操作系统的 PATH 环境变量中的目录。如果本机库依赖项是操作系统本机库,则完全没问题,因为可以在 PATH 中找到它。但是,如果本机库依赖项是您或其他人创建的本机库,则除非您将其放置在那里,否则不会在 PATH 上找到它。这种行为很奇怪、出乎意料,而且没有很好的记录,但它记录在 OpenJDK 问题跟踪器中此处您还可以在此处找到另一个 StackOverflow 答案来强化这一解释。

所以,你有几个选择。您可以使用正确的依赖顺序加载每个本机库System.loadLibrary(),也可以修改 PATH 以包含存储本机库的目录。