deg*_*nik 8 java java-native-interface loadlibrary java.library.path unsatisfiedlinkerror
我有java程序Client.class,它通过JNI使用cpp共享库libclient.so.libclient.so构建为共享并使用cpp共享库libhttp.so.
libclient.so和libhttp.so放在/home/client/lib64
Client.class 文件夹中/home/client/bin
客户端可以加载库
第一种方式很好.
export LD_LIBRARY_PATH = /home/client/lib64
java -classpath ./bin客户端
secon方式失败了.
java -classpath ./bin -Djava.library.path=./../lib64 Client
java.lang.UnsatisfiedLinkError: /home/client/lib64/libclient.so: libhttp.so: cannot open shared object file: No such file or directory
Run Code Online (Sandbox Code Playgroud)
当我将libhttp.so放入/ usr/lib64时,第二种方式正常.
如果我使用System.loadLibrary,为什么libclient.so在/ usr/lib64中寻找libhttp.so?如何在不将libhttp.so复制到/ usr/lib64的情况下修复它?
我的加载代码:
//Try load from -Djava.library.path
boolean found = false;
String lib = "client";
try {
System.loadLibrary(lib);
found = true;
} catch (UnsatisfiedLinkError e) {
e.printStackTrace();
}
//Try load from LD_LIBRARY_PATH
if (!found) {
lib = "libclient.so";
String ld_lib_path = System.getenv("LD_LIBRARY_PATH");
String[] paths = ld_lib_path.split(":");
for(int i=0; i<paths.length; i++) {
String p = paths[i];
File x = new File(p, lib);
if (x.exists()) {
System.load(x.getAbsolutePath());
found = true;
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
附加信息.
如果我用ldd测试libclient.so然后我看到:libhttp.so => not found如果我设置export LD_LIBRARY_PATH =/home/client/lib64然后我看到:libhttp.so => /home/client/lib64/libhttp.so
Phi*_*ler 10
这样做的原因是libclient.so是从你的JVM加载的java.library.path
.但是,当libclient.so尝试加载libhttp.so时,它对Java一无所知,只是使用常规的Linux方式加载共享库(动态链接器ld.so
),它查找LD_LIBRARY_PATH
和一些常见的目录,如/usr/lib64
.
我可能会LD_LIBRARY_PATH
从Java应用程序的启动脚本中使用set.如果您不想使用启动脚本,理论上可以LD_LIBRARY_PATH
从流程本身进行设置.但是,Java不允许这样做(只有System.getenv()
,没有System.setenv()
),因此您需要编写一个从Java调用的小型C库并调用putenv()
设置LD_LIBRARY_PATH
.
如果构建libclient.so
自身,则可以使用-rpath
链接器标志指定动态链接器应查找其他所需库的路径.如果在此处指定相对路径,请小心,它将被解释为相对于正在运行的应用程序的当前工作目录,而不是相对于其位置libclient.so
.要实现这一点,您需要使用$ORIGIN
as作为参数,-rpath
并注意您的shell不会扩展它.
因此,如果您想拥有libclient.so
并libhttp.so
在同一目录中,则需要使用
-rpath '$ORIGIN'
Run Code Online (Sandbox Code Playgroud)
作为构建时链接器的参数libclient.so
.如果不直接调用链接器但让编译器调用它,则需要将以下内容添加到编译器的命令行:
-Wl,-rpath,'$ORIGIN'
Run Code Online (Sandbox Code Playgroud)
有关此内容的更多信息,请参见手册页ld.so
.
归档时间: |
|
查看次数: |
20901 次 |
最近记录: |