JNI依赖库

我正在通过JNI运行库(我没有写它),并在内部调用另一个DLL。 我收到一个错误,说“找不到依赖库”,除非我把另一个DLL的路径放在系统PATH变量上(我在Windows XP上)。 我希望能够在java命令行上处理这个问题,我已经尝试将它添加到-Djava.library.path并添加到类路径中,两者都没有用(我希望-Djava.library.path可以工作)但不是类路径,但都没有工作)。 有没有办法做到这一点?

谢谢,

杰夫

  • 如果您有一个DLL名称’MyNativeDLL.dll’,那么您应该在LoadLibrary调用中使用’MyNativeDLL’。
  • 使用Dependency Walker检查MyNativeDLL.dll是否需要任何文件
  • 如果有,请将它们包含在与MyNativeDLL.dll相同的文件夹中 – 一个让它工作的尝试将其他所需文件放在System32文件夹中。

通过在所有DLL上以反向依赖顺序使用System.load(),我能够在不将任何DLL放在PATH上的情况下工作。 为了清楚起见,我在所有依赖DLL上调用System.load(),而不仅仅是JNI DLL。 您不必在Windows附带的DLL上调用System.load()(它们位于PATH上)。

我在一个Web应用程序中执行此操作,其中jar包含已解压缩的DLL。 你的情况似乎更简单,所以我认为它应该有效。 我一般遵循这里的解决方案: 如何制作包含DLL文件的JAR文件?

这对我帮助很大。 还管理加载使用cygwin构建的JNI dll:

第一:

/* conditioned if OS is windows because also need it to work in Linux env. */ System.loadLibrary("cygwin1"); 

然后:

 System.loadLibrary("mylib"); 

在Windows上,这需要设置java.library.path以匹配两个库位置。

如果从Eclipse运行,则此设置可能会被java构建路径中的“本机库位置”替换(在JRE库设置中)。

但是,仍然觉得这有点棘手。

我已经使用JNA成功地将一个文件夹注入到PATH变量中。 如果您希望在应用程序旁边部署依赖DLL而不会污染全局环境或搞乱显式DLL加载顺序,则可以将其用作解决方法。

但是,我不清楚类加载器生命周期如何影响这一点。 我只在NetBeans模块系统下尝试过这种技术,但是如果你查看loadLibrary的ClassLoader类代码,你会看到它缓存了一些路径变量。 创建新的类加载器以加载库可能需要也可能不需要。

缺点是你需要使用JNA或JNI。 此外,它似乎是一个相当严重的黑客。 有关如何使用JNA设置环境变量的示例,请参见此处 。