繁体   English   中英

从java.library.path专门加载Native Library

[英]Loading Native Library from java.library.path specifically

我只是试图制作一个玩具程序,以将本机代码绑定到Java只是为了好玩。 已经能够使用System.load("/FULLPATH/mylib.so") 成功运行该程序,但是使用System.loadLibrary()java.library.path专门加载库时遇到了麻烦。

我使用的工具:

  • gcc 4.8.5 20150623(Red Hat 4.8.5-4)
  • java / javac版本“ 1.8.0_66”(HotSpot 64位)
  • CentOS 7(64位)

生成顺序(第一段中提到的两个版本相同)。

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"); 只是为了完整性。

让我们检查一下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 ,后者本身会调用dlopen(filename)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM