我正在开发一个使用JNI的Java项目。 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表示可以安全地忽略这些警告。
我按照建议here修复了mylib.dll中的方法名称。方法名称在某种程度上被编译器破坏了,但我添加了链接器标志,现在dll方法名称与我的jni头文件中的名称完全匹配。
我将所有这些DLL放在同一目录中 - 与调用它们的.jar相同的目录 - 以确保它们位于正确的路径上。
没有骰子。
有谁知道发生了什么事?
我正在使用MacBook pro(通过Parallels)在Visual Studio 2010中进行开发。我正在使用toshiba笔记本电脑在Windows XP中进行测试。
答案 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)
在将javacv
和opencv
与Eclipse结合使用时,在XP机器上遇到了同样的问题。原来我错过了以下文件:
安装完成后,项目编译并运行正常。
答案 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)
答案 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)
Visual C++ Redistributable for VS2012
VSU_4\vcredist_x64.exe
或VSU_4\vcredist_x84.exe
,具体取决于您的系统配置dll
文件放在lib
文件夹中,以及其他库(例如\lib\win32-x86\your dll files
)。