我对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字段指定的共享对象,而不是使用给链接器的文件名。
那么这意味着什么呢?当最终可执行文件运行时,链接器将尝试加载??而不是以??的名义加载?
这对于一个系统来说是很有用的,因为在这个系统中,一个库可以以多个名字存在,例如: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代码总是加载一个兼容的版本。
来自GCC-HOWTO。
每个库都有一个soname. 当链接器在它搜索的库中找到其中一个时,它就会把这个子名嵌入到二进制文件中,而不是它正在寻找的实际文件名。在运行时,动态加载器将搜索一个带有子名的文件,而不是库的文件名。因此,一个名为libfoo.so的库可能有一个子名为libbar.so的文件,所有与它链接的程序在启动时都会寻找libbar.so。
在你的例子中,子名是 libnative.so
与文件名不同 libnativelib.so
...你必须要用符号链接 libnative.so
到 libnativelib.so
以允许动态加载器找到共享的lib。