0

我对http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html上的 JNI 文章有疑问。

gcc  -o libnativelib.so -shared -Wl,-soname,libnative.so  
     -I/export/home/jdk1.2/include 
     -I/export/home/jdk1.2/include/linux nativelib.c  
     -static -lc

我想我对'-o libnativelib.so'和'-Wl,-soname,libnative.so'的功能仍然有些困惑。

'-o libnativelib.so' 指定 gcc 的输出文件名为 libnativelib.so。据我了解,它是从 JAVA 端加载的库名称,如文章所示:

  static {
    System.loadLibrary("nativelib");
  }

那么'-Wl,-soname,libnative.so'有什么用呢?

我在 ld 选项手册上找到了以下信息:

-soname=名称

创建 ELF 共享对象时,将内部 DT_SONAME 字段设置为指定名称。当可执行文件与具有 DT_SONAME 字段的共享对象链接时,当可执行文件运行时,动态链接器将尝试加载由 DT_SONAME 字段指定的共享对象,而不是使用链接器提供的文件名。

那么这是什么意思呢?当最终的可执行文件运行时,链接器将尝试加载??而不是 ??以??

4

2 回答 2

0

这对于一个系统很有用,其中一个库可以以多个名称存在,例如:libz.so、libz.so.1、libz.so.1.2.3。所有这些库都是指向一个文件的符号链接,其中的 DT_SONAME 指向“libz.so.1”。当您将代码链接到 libz.so 时,它将在可执行文件中记录对“libz.so.1”的依赖关系。当您的文件在另一个系统上执行时,例如包含 libz.so.1.2.5,它仍然可以工作,因为它会查找 libz.so.1。但是如果目标系统有更新的版本,比如 libz.2.3.4,它就会失败,因为 libz.so.2 而不是 libz.so.1。

DT_SONAME 字段仅供链接器使用。使用 System.loadLibrary() 时,文件名由您指定,不使用该选项的值。如果你愿意,你可以为你的 libnative 实现一个类似的版本控制方案,以确保你的 java 代码总是加载一个兼容的版本。

于 2012-08-22T11:48:27.127 回答
0

来自 GCC-HOWTO:

每个库都有一个 soname。当链接器在它正在搜索的库中找到其中之一时,它会将 soname 嵌入到二进制文件中,而不是它正在查看的实际文件名。在运行时,动态加载器将搜索一个名为 soname 的文件,而不是库文件名。因此,一个名为 libfoo.so 的库可以有一个 soname libbar.so,并且所有链接到它的程序都会在启动时查找 libbar.so。

在您的情况下, sonamelibnative.so与 file name 不同libnativelib.so。您必须进行符号链接libnative.solibnativelib.so允许动态加载程序找到共享库。

于 2012-08-22T12:10:15.290 回答