amd64上碰到的小问题_动态连接库

第一次在64位系统上(amd64, debian, gcc 4, jdk 1.5.0_10)跑东西, 简单记录下...

程序很简单, java通过jni调用C++封装的动态链接库, 同时用了opencv。这个程序在32位debian上顺利编译运行。

一开始很顺利, 下载opencv源码, 编译生成so(/usr/local/lib), 添加/etc/ld.so.conf.d/opencv.conf, 执行ldconfig(其实也可以加入到LD_LIBRARY_PATH环境变量中, 见下文有关ld.so内容), 编译运行sample程序( 参照).

接下来编译源码时出错了, GOOGLE一把, 发现 有个人说在64位上编译要在g++编译时带选项-fPIC, 且一定要加到最前面...

编译成功, 生成出lib***.so, jni加载动态库时, windows下会查找***.dll, 而linux/solaris下会查找lib***.so.

执行的时候却出错:
java: symbol lookup error: /opt/MyDemo/libPicMatcherService.so: undefined symbol: _Z24combinePrecomputedHashesPjS_ii

诡异的事情, 那函数明明在, 也不是JNI接口, 只是CPP内部调用的函数, 并且32位上跑都没问题...可能的原因或者是64位, 或者是gcc 4的原因(32位机上用的是gcc 3.*).

后来把该CPP函数的定义中的inline去掉就可以了...

对于Java5及更早版本JNI应用中产生的莫名的错误, 可以考虑在java6下运行。因为java6会产生更详细准确的错误信息, 便于找出错误的根源.

另外, 在应用中使用到很多linux动态库的东西, 摘录了一些相关的基础知识和操作.

Windows和Linux相似概念的对应关系如下:
"Windows             Linux
动态连接库(DLL)     Shared Object
目标文件(.obj)      文件名结尾常是 .o
可执行文件(.exe)    Executable(文件名无特定标志)
连接器(link.exe)    Linker Editor (ld)
加载器(exec/loader) Dynamic Linker (ld-linux.so)
段(segment)         节(section)

在Windows中,连接生成动态连接库时要指定一个首地址。应用程序运行时,加载器将尽可能把动态连接库装入到该地址;如果地址已被占用,该动态连接库只能被加载到其它地址空间内,这时就要对库中的代码和数据进行修补,或叫做重定位。如此一来,库的多个实例在内存中经过重定位后,彼此将不尽相同,自然不再能共享了。为了避免这个缺陷,Windows自带的库都指定了互不重叠的地址,尽管如此,其它软件厂商的产品仍然不可避免的使用重叠地址,由此部分丧失了使用动态连接库的好处。

在Linux中,为了达到更好的共享性能,使用了与Windows不一样的策略:浮动代码(Position Independent Code,简称PIC)。具体说,使用的转移指令都是相对于当前程序计数器(IP)的偏移量;代码中引用变量、函数的地址都是相对于某个基地址的偏移量。 总之,从不引用一个绝对地址。这样,动态连接库无论被加载到什么地址空间,不用修补代码就可以正常工作。既然只有一份代码,就容易实现共享了。

值得指出,此处所指的共享,是指为了节省存储器,多个进程使用动态连接库代码段、只读数据段在内存中的唯一映像;另一种常用的共享定义,是指多个进程对同一 段(可能是动态分配的)存储区进行读写,实现进程间通信(IPC)。后一种共享定义与本文无可执行文件运行时,加载器根据这个标记,检查该库是否已经被其 它可执行文件加载进内存。如果已存在于内存中,不用再从磁盘上加载,只要共享内存中已有的代码即可。这样磁盘、内存中始终只有一份代码,较静态库为优。(摘自 http://blog.csdn.net/Kendiv/archive/2008/03/29/2229406.aspx)"

在Linux下, 有关动态库的操作主要有ldd, ldconfig, ld.so/ld-linux.so.

ldd命令打印share library的依赖关系.

"ldconfig命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如前介绍,lib*.so*),进而创建出动态装入程序(ld.so)所需的连接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表. (摘自 http://www.lslnet.com/linux/dosc1/19/linux-190821.htm)"

"ld.so/ld-linux.so - dynamic linker/loader

DESCRIPTION
   ld.so  loads  the shared libraries needed by a program, prepares the program to run,
   and then runs it.  Unless explicitly specified via the -static option to  ld  during
   compilation,  all  Linux  programs are incomplete and require further linking at run
   time.

   The necessary shared libraries needed by the program are searched for in the follow-
   ing order

   o      Using  the  environment  variable  LD_LIBRARY_PATH  (LD_AOUT_LIBRARY_PATH for
          a.out programs).  Except if the executable  is  a  setuid/setgid  binary,  in
          which case it is ignored.

   o      From the cache file /etc/ld.so.cache which contains a compiled list of candi-
          date libraries previously found in the augmented library path.

   o      In the default path /usr/lib, and then /lib.(摘自man ld.so)"

你可能感兴趣的:(Java,C/C++,Linux,library,debian,jni,windows,linux,compilation)