我想从其他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。
预先感谢!
答案 0 :(得分:0)
从本机库加载从属库是纯粹的OS操作,因此不在Java控制范围之内。不幸的是,您无法使用Java提供的工具解决此问题。
如您所述,在Linux库中,搜索路径可以由LD_LIBRARY_PATH环境变量设置,但是无法修改已经运行的JVM进程的环境变量(请参阅here并建议使用{{ 3}}确实不适用于非调试情况。
您描述的问题是Windows hack using gdb的JDK错误,带有注释我们真的无能为力。
但是,对于您的情况,应该有一个简单的解决方案:
在加载 libb.so 之前先显式加载依赖库 liba.so :
static {
System.loadLibrary("a");
System.loadLibrary("b");
}
对于具有多个依赖库和更深层次的依赖层次结构的情况,请以相反的顺序手动加载所有依赖库。
答案 1 :(得分:0)
假设您控制共享对象liba.so
和libb.so
的位置,请用embedded RPATH
set so that it can locate liba.so
编译libb.so
共享对象。
如果两个共享对象位于shame目录中,则可以使用:
g++ -shared -o libb.so -fPIC b.cc -L/x/y/z -la -Wl,-rpath,'$ORIGIN/.'
($ORIGIN
本身可以工作,但是我想使用$ORIGIN/.
清楚地显示结果是一个目录。如果您有公用的bin
和lib
目录树,始终将$ORIGIN/../lib
用于可执行文件和共享对象也是IMO的一个好主意。)
-Wl,-rpath,'$ORIGIN/.
将在RPATH
共享对象中设置libb.so
,以便运行时链接程序在同一目录libb.so
中搜索liba.so
。