Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows上的Java JNI和依赖库_Java_Java Native Interface_Java.library.path - Fatal编程技术网

Windows上的Java JNI和依赖库

Windows上的Java JNI和依赖库,java,java-native-interface,java.library.path,Java,Java Native Interface,Java.library.path,长话短说:我有一个可执行jar,它调用jni.dll,它依赖于lib.dll。我得到了一个非常可怕的不满意的链接错误 答案很接近,但根据我的经验,它并没有解决问题。即使在java.library.path中指定了dll所在的文件夹,它也不会工作。我还必须更改WindowsPATH环境变量。事实上,Windows上默认的java.library.path似乎是path 有什么“漂亮”的方法来解决这个问题吗?我想为Windows构建一个安装程序,我想知道如何处理这个问题,这样最终用户就不必做任何手动

长话短说:我有一个可执行jar,它调用
jni.dll
,它依赖于
lib.dll
。我得到了一个非常可怕的
不满意的链接错误

答案很接近,但根据我的经验,它并没有解决问题。即使在
java.library.path
中指定了dll所在的文件夹,它也不会工作。我还必须更改Windows
PATH
环境变量。事实上,Windows上默认的
java.library.path
似乎是
path

有什么“漂亮”的方法来解决这个问题吗?我想为Windows构建一个安装程序,我想知道如何处理这个问题,这样最终用户就不必做任何手动工作

编辑:

我实现了以下内容:应用程序附带了一个名为“native_libs”的文件夹,其中包含所有受支持体系结构的动态库。结构如下:

/
+- native_libs/
   +- windows/
   |  +- x86/
   |  |  +- ...
   |  +- x64/
   |     +- ...
   |
   +- linux/
   |  +- x86/
   |  |  +- ...
   |  +- x64/
   |     +- ...
   |
   +- libs/
      +- ...
在运行时,当应用程序初始化时,会检测到正确的JRE体系结构和系统操作系统,并将正确的库文件复制到libs/文件夹。
java.library.path
也在运行时使用常见的hack进行设置。最后,使用本机启动器设置windows的
PATH
环境变量


还有改进的余地吗?也许将dll复制到与
jar
文件相同的目录中,就不需要设置
java.library.path
path
变量了?我还需要研究使用
System.load()
加载dll,这将消除复制文件的需要。

java.library.path
指定
System.loadLibrary()
查找动态库文件的目录。如果更改代码中的
java.library.path
系统属性,则不会产生任何效果。有一些黑客让Java“忘记”初始值并重新评估
Java.library.path
系统属性的内容



但是,依赖库不是由Java加载的,而是由Windows加载的。Windows不关心
java.library.path
,它只关心
path
环境变量。您唯一的选择是为Java进程调整
PATH
。例如,如果从批处理文件启动,请在java调用之前更改
PATH
环境变量。

如果问题是操作系统找不到依赖项库,是否尝试通过
System.loadLibrary()加载它
在加载主库之前?

最简单的解决方案是在执行时确保所有.dll都在“.”中。

将jni.dll所依赖的dll放在“当前工作目录”中,在运行时检查此
System.getProperty(“user.dir”)
以了解“当前工作目录”是什么

我理解整个概念,我想要的是一种方法来修复我提到的“漂亮”。不幸的是,运行批处理文件并不“漂亮”。你还有别的想法吗?(顺便说一句,当路径中有“.”时,它是否能够找到依赖的dll?因为显然它没有)。是的,我使用了这样一种方法来确保正确的JNI是根据OS/JRE架构加载的,因为您不能在运行的进程中调整环境变量。如果当前目录包含依赖库,则“.”将起作用。我建议使用本机启动器生成器,其中大多数允许您调整本机库路径。至于黑客,我回答的要点是解释为什么这对依赖库不起作用。我赞成澄清所有感兴趣的人的工作方式--“本机启动器生成器”这对谷歌来说是一个完美的术语,谢谢@IngoKegel我同意Windows应该使用%PATH%加载
依赖库
。但是在我的场景中,我将包含
依赖DLL
的文件夹放入%PATH%中,但仍然找不到DLL。但如果我将依赖DLL放在JDK的bin文件夹中,它就会工作。因此,我的一些团队成员盲目地将所有DLL放入JDK的bin文件夹,我认为这是一个混乱。这里的详细信息:如果你能顺便来看我,我将不胜感激。是否有其他针对此错误的书面说明?比如“找不到依赖库”或者类似的东西?就是这样。我认为我设计了一个相当愚蠢的解决方案,但它是有效的,至少对用户是透明的。一旦我确信它能工作,我将与您共享。您可以尝试使用依赖项漫游器查看缺少哪些库:“使用
System预加载”DLL。load()
在Windows上可以工作,除非DLL之间存在循环依赖项。
jni.dll
lib.dll
之间是否存在循环依赖关系?@SamuelAudet不存在循环依赖关系,请检查我下面的评论。@alkar:如果没有任何效果,则有
System.load()
会获取dll的完整文件路径。@alkar:另外,发布完整的堆栈跟踪,请。@EJP:在这些方法的javadoc中,没有任何地方说只加载jni库。请看下面的答案:人们实际上是通过在主库之前加载依赖项来使它工作的。@alkar和EJP:是的,它工作。我应该知道,我一直在Windows上使用黑客软件。您的代码可能有其他问题。@SamuelAudet:是的,根据google的说法应该可以工作,一定是我没有通过lib的两个运行时依赖项。dllI需要检查一下。是否确定Windows将始终在“.”中查找dll?是的,这是一个向后兼容性问题: