为JNI创建.so时的gcc选项

时间:2012-08-22 11:16:44

标签: gcc linker java-native-interface

我对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字段指定的共享对象,而不是使用为链接器指定的文件名。

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

我很困惑。有人可以帮忙解释一下吗?

谢谢,

2 个答案:

答案 0 :(得分: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代码始终加载兼容版本。

答案 1 :(得分:0)

来自GCC-HOWTO:

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

在您的情况下,soname libnative.so与文件名libnativelib.so不同。 您必须将libnative.so符号链接到libnativelib.so以允许动态加载程序找到共享库。