Windows 上的 Java JNI 和依赖库
长话短说:我有一个可执行的 jar,它调用依赖于 lib.dll
的 jni.dll
.我得到了非常可怕的 UnsatisfiedLinkError
.
Long story short: I have an executable jar, that calls jni.dll
which is dependent on lib.dll
. And I'm getting the oh-so-dreaded UnsatisfiedLinkError
.
这个答案非常接近,但根据我的经验,它无法解决问题.即使在 java.library.path
中指定了 dll 所在的文件夹,它也不起作用.我还必须更改 Windows PATH
环境变量.其实Windows上默认的java.library.path
好像是PATH
.
This answer comes pretty close, yet it fails to solve the problem, from my experience. Even when the folder where the dll's reside is specified in java.library.path
, it will not work. I have to change the Windows PATH
environment variable as well. In fact, the default java.library.path
on Windows seems to be PATH
.
有什么漂亮"的方法可以解决这个问题吗?我想为 Windows 构建一个安装程序,我想知道如何处理这个问题,以便最终用户不必做任何手动工作.
Is there any "pretty" way to fix this? I want to build an installer for Windows and I'm wondering how I would deal with this issue, so that the end-user will not have to do any manual work.
我实现的内容如下:该应用程序附带一个名为native_libs"的文件夹,其中包含适用于所有受支持架构的动态库.结构如下:
What I implemented is the following: the application ships with a folder called "native_libs" which has dynamic libraries for all supported architectures. The structure is the following:
/
+- native_libs/
+- windows/
| +- x86/
| | +- ...
| +- x64/
| +- ...
|
+- linux/
| +- x86/
| | +- ...
| +- x64/
| +- ...
|
+- libs/
+- ...
在运行时,当应用程序初始化时,会检测到正确的 JRE 架构和系统操作系统,并将正确的库文件复制到 libs/文件夹中.java.library.path
正在运行时设置以及使用常见的黑客.最后,使用本机启动器设置 Windows 的 PATH
环境变量.
On runtime, while the application initializes, the correct JRE architecture and System OS are detected and the proper library files are copied to the libs/ folder. The java.library.path
is being set on runtime as well using a common hack. Finally, the PATH
environment variable for windows is set using a native launcher.
还有改进的余地吗?也许将 dll 复制到与 jar
文件相同的目录中将不需要设置 java.library.path
和 PATH
变量?我还需要研究使用 System.load()
加载 dll,这将消除复制文件的需要.
Any room for improvement? Maybe copying the dll's in the same directory as the jar
file would negate the need for setting the java.library.path
and PATH
variables? I need to investigate loading the dll's with System.load()
as well, which will negate the need to copy files.
推荐答案
java.library.path
指定System.loadLibrary()
查找动态库的目录文件.如果您更改代码中的 java.library.path
系统属性,它不会产生任何影响.有一些技巧可以让 Java 忘记"初始值并重新评估 java.library.path
系统属性的内容.
java.library.path
specifies the directories where System.loadLibrary()
looks for the dynamic library file. If you change the java.library.path
system property in your code, it will not have any effect. There are hacks to make Java "forget" the initial value and re-evaluate the contents of the java.library.path
system property.
但是,依赖库不是由 Java 加载的,而是由 Windows 加载的.Windows 不关心 java.library.path
,它只关心 PATH
环境变量.您唯一的选择是为您的 Java 进程调整 PATH
.例如,如果您从批处理文件启动它,请在调用 java 之前更改 PATH
环境变量.
However, the dependent library is not loaded by Java, it's loaded by Windows. Windows does not care about java.library.path
, it only cares about the PATH
environment variable. Your only option is to adjust PATH
for your Java process. For example, if you start it from a batch file, change the PATH
environment variable right before the java invocation.
相关文章