java - 如何通过 Java 代码影响 System.loadLibrary() 的搜索路径?

标签 java java-native-interface

在 Java 项目中,我正在使用第三方库,它通过以下方式加载一些 native 库

System.loadLibrary("libName");

我希望能够从我的应用程序中影响此方法的搜索路径,以便用户不需要在命令行上指定正确的 java.library.path 值(此值取决于当前的操作系统和架构)。例如,在 Windows 上我想将它设置为“lib/native/windows”,在 Linux 32 位上设置为“lib/native/linux32”等。

我试过了

System.setProperty("java.library.path", ...)

但这被忽略了,显然是因为 JVM 在我的代码运行之前只读取了一次这个属性。

在使用依赖于它的Java库之前,我还尝试加载 native 库

System.load("fullPath/lib")

本次调用成功,但再次使用System.loadLibrary()加载 native 库时仍会出现UnsatisfiedLinkError。

我找到的唯一方法如下:

  • 添加抽象外部库的整个 API 的接口(interface)。
  • 在其余代码中仅使用这些接口(interface)。
  • 添加实现接口(interface)并委托(delegate)给库的类。
  • 写一个自己的ClassLoader,即
    • 覆盖 findLibary() 以便在正确的路径中找到 native 库
    • 覆盖 loadClass() 并自行加载外部库和包装层的所有类,而不是像默认的 ClassLoader 那样尝试委托(delegate)给其父级
  • 确保接口(interface)使用正常的 ClassLoader 加载,包装类和外部库使用我自己的 ClassLoader 加载。

这行得通,但我发现它非常复杂并且需要付出很多努力,因为我需要添加所有这些接口(interface)。有没有更简单的方法?

最佳答案

我需要更改单元测试的 dll 路径。我尝试了以下 hack,它奏效了:

System.setProperty( "java.library.path", "/path/to/libs" ); 
Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );

有关说明,请参阅 original link .

关于java - 如何通过 Java 代码影响 System.loadLibrary() 的搜索路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5013547/

相关文章:

java - 资源 DATASOURCE 在 LocalTransactionContainment 的清理中回滚

java - Spring安全+LDAP。无法调试

java - 如何使用 Java Runtime.exec() 和 Windows REG 实用程序来读取/更新/删除 HKEY_LOCAL_MACHINE\...\CurrentVersion\Run 中的条目?

Java Native Hook 陷入无限循环

Xamarin Android 绑定(bind)库自定义命名空间无法识别

java - 用于传输文件的 jboss Web 服务

java - 打开应用程序, map 放大到当前位置

java - 使用 easymock 对方法进行单元测试

java - 一个 native 方法可以从另一个 native 方法调用吗?

java - 使用JNI访问C中Java对象中的Java对象