【发布时间】:2021-04-01 20:52:08
【问题描述】:
在一个 Java 项目中,我正在使用一个第三方库,它通过以下方式加载一些本机库
System.loadLibrary("libName");
我希望能够从我的应用程序中影响此方法的搜索路径,以便用户无需在命令行上指定正确的 java.library.path 值(此值取决于当前的操作系统和架构)。例如,在 Windows 上我想将其设置为“lib/native/windows”,在 Linux 32 位上设置为“lib/native/linux32”等。
我试过了
System.setProperty("java.library.path", ...)
但这被忽略了,显然是因为 JVM 在我的代码运行之前只读取了一次这个属性。
我还尝试在使用依赖于它的 Java 库之前加载本机库
System.load("fullPath/lib")
这个调用成功了,但是当使用 System.loadLibrary() 再次加载原生库时,仍然会出现 UnsatisfiedLinkError。
我找到的唯一方法如下:
- 添加抽象外部库的整个 API 的接口。
- 在其余代码中仅使用这些接口。
- 添加实现接口并委托给库的类。
- 编写自己的类加载器,即
- 覆盖 findLibary() 以便在正确的路径中找到本机库
- 覆盖 loadClass() 并自行加载外部库和包装层的所有类,而不是像默认的 ClassLoader 那样尝试委托给其父级
- 确保使用普通的 ClassLoader 加载接口,并使用我自己的 ClassLoader 加载包装类和外部库。
这行得通,但我觉得它很复杂,而且很费力,因为我需要添加所有这些接口。有没有更简单的方法?
【问题讨论】:
-
是否与
System.load("fullPath/lib/native/windows/libName.dll")一起使用?你为什么用System.loadLibrary(..)重新加载它? -
@dacwe 是的,它确实有效。但是第三方库尝试用 System.loadLibrary(..) 再次加载,失败了。
标签: java java-native-interface