【发布时间】:2019-01-25 21:50:00
【问题描述】:
我想从其他 libb.so 调用 liba.so 的某些函数。 libb.so 是动态库,它实现了我在 JNI 中使用 System.loadLibrary("b") 加载的本机方法。首先,我使用 java.library.path 为 jni 中的两个 .so 设置了完整路径,但是当我运行我的 java 程序时,同时加载共享库 libb.so, 它给出了以下错误:
Exception in thread "main" java.lang.UnsatisfiedLinkError: x/y/z/libb.so: liba.so: cannot open shared object file: No such file or directory.
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
-
首先我在编译过程中将共享库 liba.so 与其他共享库 libb.so 链接在一起
g++ -shared -o libb.so -fPIC b.cc -L/x/y/z -la
(说liba.so的完整路径是/x/y/z)
在 JNI 中,我实用地设置了 java.library.path,其中包含 liba.so、libb.so 的完整路径,然后我习惯于将 JNI 本机库 libb.so 加载为
(说 libb.so 的完整路径是 a/b/c 和 liba.so 的完整路径是 x/y/z。)
String libpath = "x/y/z" + "a/b/c";
System.setProperty( "java.library.path", libpath);
try {
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );
}
catch (Exception e)
{
System.out.println(e);
}
// 在这里我可以打印/获取正确的 java.library.path。 (两个共享库的路径都正确保存到 java.library.path 中)
static {
System.loadLibrary("b");
}
当我的java程序加载这个静态块的动态库时,它给出了以下错误:
线程“main”中的异常 java.lang.UnsatisfiedLinkError: x/y/z/liba.so: libb.so: 无法打开共享对象文件:没有这样的文件或目录。
注意:当我在 LD_LIBRARY_PATH 中设置 liba.so 的路径时,它可以正常工作,没有任何错误。但我不想在 SHELL 中设置 LD_LIBRARY_PATH。只是我想在程序本身中设置 java.library.path 或 LD_LIBRARY_PATH。
提前致谢!
【问题讨论】:
-
@Oo.oO,当我在 LD_LIBRARY_PATH 中设置 liba.so 的路径时,它就可以工作了。但是当我尝试通过程序在 java.library.path 中设置依赖库(liba.so)路径时,它会出错。
-
它不适用于 java.library.path。一旦进入 liba.so 你依赖于系统。
-
@Oo.oO,即使我在程序内部的 LD_LIBRARY_PATH 中设置 liba.so 的路径,它也不起作用。我认为一旦程序已经启动,您就无法更改程序内部正在运行的进程的 LD_LIBRARY_PATH 设置。我搜索了各种讨论,如果不在程序启动前在 SHELL 中设置 LD_LIBRARY_PATH,我无法找到克服上述错误的方法。
标签: linux java-native-interface shared-libraries dynamic-loading java.library.path