我只是想制作一个玩具程序,将本机代码绑定到java只是为了好玩。 我已成功能够使用System.load("/FULLPATH/mylib.so")
运行该程序,但无法使用java.library.path
专门从System.loadLibrary()
加载库。
我使用的工具:
构建序列(第一段中提到的两个版本都相同)。
rm TestIt.class mylib.so TestIt.h javac TestIt.java javah -stubs TestIt gcc -shared -I/$JDK8_HOME/include/ -I/$JDK8_HOME/include/linux/ -fPIC nativeTestItImpl.c -o mylib.so
加载库的Java代码(只是一个静态初始化程序):
static { System.out.println("System.getProperty(\"java.library.path\") is: " + System.getProperty("java.library.path")); System.loadLibrary("mylib"); //System.load("/FULLPATH/mylib.so");// ***This works*** }
我是如何尝试设置库路径的:
java -Djava.library.path=/FULLPATH TestIt java -Djava.library.path=/FULLPATH/mylib.so TestIt java -Djava.library.path=. TestIt #appeared as '.' java -Djava.library.path=/FULLPATH:$PATH TestIt #NOTE: DEFLT_LIB_PATH was the output of the above print statement when # running "java TestIt" java -Djava.library.path=/FULLPATH:$DEFLT_LIB_PATH TestIt set LD_LIBRARY_PATH=/FULLPATH && java TestIt ##did not appear in printout of lib export LD_LIBRARY_PATH=/FULLPATH && java TestIt ##preppended /FULLPATH: to DEFLT_LIB_PATH
所有版本打印出来,预期例外标有" ##"上方。
所有情况下都有错误:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no mylib in java.library.path
完整路径没有空格或特殊字符,所以我很遗憾为什么会这样。
还为了完整性而尝试了System.loadLibrary("mylib.so");
。
答案 0 :(得分:1)
让我们来看看Javadoc说的话:
使用指定的库名称加载动态库。包含本机代码的文件从本地文件系统从常规获取库文件的位置加载。此过程的详细信息取决于实现。 从库名称到特定文件名的映射是以系统特定的方式完成的。
由于您使用的是CentOS 7,因此我将专注于Linux。
您面临的问题是您没有遵循针对Linux的未签名系统特定合同。 JVM在Linux上的作用是将对System.loadLibrary("foo")
的呼叫转换为对dlopen("libfoo.so")
的呼叫。如果重命名库并修复传递给System.loadLibrary
的参数,它应该可以正常工作。
我不知道有一份“官方”文件说明了这份合同,但它很可能存在于某个地方。
如果您想玩得开心,可以下载OpenJDK并关注调用链。您应该最终得到hotspot/src/os/linux/vm/os_linux.cpp
中定义的这段代码:
bool os::dll_build_name(char* buffer, size_t buflen,
const char* pname, const char* fname) {
bool retval = false;
// Copied from libhpi
const size_t pnamelen = pname ? strlen(pname) : 0;
// Return error on buffer overflow.
if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
return retval;
}
if (pnamelen == 0) {
snprintf(buffer, buflen, "lib%s.so", fname);
retval = true;
} else [...]
os::dll_build_name
用于获取传递给filename
os::dll_load
的{{1}}参数,该参数本身会调用dlopen(filename)
。