为JNI创建.so时的gcc选项

问题描述 投票:0回答:2

我对JNI的一篇文章有一个问题。http:/java.sun.comdeveloperonlineTrainingProgrammingJDCBookjniexamp.html。.

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=name

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

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

gcc linker java-native-interface
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这个字段只有linker使用。当你使用System.loadLibrary()时,文件名由你指定,这个选项的值不会被使用。如果你愿意,你可以为你的libnative实现类似的版本方案,以确保你的java代码总是加载一个兼容的版本。


0
投票

来自GCC-HOWTO。

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

在你的例子中,子名是 libnative.so 与文件名不同 libnativelib.so...你必须要用符号链接 libnative.solibnativelib.so 以允许动态加载器找到共享的lib。

© www.soinside.com 2019 - 2024. All rights reserved.