【发布时间】:2012-03-04 21:19:37
【问题描述】:
Java VM 在执行 JNI 函数时出现“符号查找错误”怎么办?符号查找错误不在支持 JNI 接口的主共享库中,也不是直接在链接到主库的库中,而是在链接到链接到 JNI 共享库的库中? (多么尴尬的一句话☺)特别是,当你不控制包含违规符号的库的代码时,你会怎么做?
我在使用 JNI 访问科学相机 (Andor NEO CMOS) 的 SDK 时遇到问题。我在 RHEL 6 上使用 Netbeans C/C++ 插件来创建一个共享库 (AndorC.so),它基本上围绕相机 SDK 提供的方法创建 JNI 包装器。摄像头 SDK 提供了一组访问摄像头的方法,这些方法封装在一个共享对象库 (libatcore.so) 中。 libatcore.so 库使用了一系列附加库,libatdevregcam.so(用于真实相机)、libatdevsimcam.so(用于模拟相机)、libatcl_bitflow.so(低级视频板驱动程序)等。
我已经对相机 SDK 进行了广泛的测试,我可以通过 C/C++ 轻松访问相机。我已经链接到从测试 C 程序(使用单独的头文件)实现 JNI 函数的共享库(AndorC)并且一切运行正常(即我可以读取图像并且程序正常完成)。
我的 Java 代码可以通过 JNI 接口从 SDK 执行“InitializeLibrary”和“FinalizeLibrary”函数,因此找到主 libatcore.so 库或我的 AndorC.so 库没有问题。 JNI 的基本设置似乎没有任何问题。但是,当我尝试为相机执行“打开”功能(即实际连接到真实和/或模拟相机的功能)时,我在 libatcore.so 库使用的库之一中遇到未定义符号错误运行时(libdevsimcam.so)。
/usr/local/java/jdk1.7.0_03/jre/bin/java: symbol lookup error: /usr/local/lib/libatdevsimcam.so: undefined symbol: _ZN20TAndorLibDebugOutput6OutputEPKciS1_xx24TAndorDebugFunctionLevel16TAndorDebugLevelS1_z
Java Result: 127
基本上,Java VM 的 libatcore.so(即主库文件)没有问题,定位相关的运行时库(/usr/local/lib/libatdevsimcam.so)也没有问题)但是当它试图打开相机时它会在该库中遇到一个未定义的符号(注意我实际上是在打开真实的相机而不是模拟的相机)。
当我检查每个库(libAndorC.so、libatcore.so、libatdevsimcam.so)的依赖关系时,我没有找到任何未定义的符号。显然,当程序直接从 C/C++ 运行时,libatdevsimcam.so 库中的未定义符号不是问题,但当 Java VM 尝试加载 libatdevsimcam.so 时会导致问题。
libAndorC.so
linux-vdso.so.1 => (0x00007fff507ff000)
libatcore.so.3 => /usr/local/lib/libatcore.so.3 (0x00007fe23a278000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fe239f4a000)
libm.so.6 => /lib64/libm.so.6 (0x00007fe239cc6000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fe239ab0000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe239730000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe239513000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fe23930f000)
librt.so.1 => /lib64/librt.so.1 (0x00007fe239106000)
/lib64/ld-linux-x86-64.so.2 (0x0000003f07000000)
libatcore.so
linux-vdso.so.1 => (0x00007fffd53ff000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f7e6b645000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f7e6b440000)
librt.so.1 => /lib64/librt.so.1 (0x00007f7e6b238000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f7e6af31000)
libm.so.6 => /lib64/libm.so.6 (0x00007f7e6acac000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f7e6aa96000)
libc.so.6 => /lib64/libc.so.6 (0x00007f7e6a717000)
/lib64/ld-linux-x86-64.so.2 (0x0000003f07000000)
ldd libatdevsimcam.so
linux-vdso.so.1 => (0x00007fff247ef000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f5219dc4000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f5219bbf000)
librt.so.1 => /lib64/librt.so.1 (0x00007f52199b7000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f52196b0000)
libm.so.6 => /lib64/libm.so.6 (0x00007f521942b000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f5219215000)
libc.so.6 => /lib64/libc.so.6 (0x00007f5218e96000)
/lib64/ld-linux-x86-64.so.2 (0x0000003f07000000)
当我专门检查 Java VM 有问题的符号时,很明显该符号是未定义的。
nm libatdevsimcam.so | grep _ZN20TAndor
U _ZN20TAndorLibDebugOutput6OutputEPKciS1_xx24TAndorDebugFunctionLevel16TAndorDebugLevelS1_z
我认为该符号可能未在 libatdevsimcam.so 库的发行版与调试版中定义,因此我尝试构建 libAndorC.so 的发行版,但遇到了同样的问题。
我有两个基本问题
这可能是 C++ 名称修改的问题吗?我尝试使用 gcc 而不是 g++ 编译我的相机测试程序,但遇到了大量编译错误。我读过 C++ 名称修改会导致问题。
这是不是厂家提供的libatdevsimcam.so库有问题?我无法控制 Andor 提供的支持相机的代码(我所能做的就是抱怨)。
我基本上被困在这一点上,因为所有 SDK 函数都需要对“Open”方法返回的相机句柄的引用。如果我无法打开相机,我将无法继续为我需要的相机开发 JNI 接口。
我对这个问题进行了广泛的研究,但没有找到任何直接解决该问题的答案。这不是 JNI 帖子中常见的标准“不满意的链接”错误,基本的 JNI 功能似乎可以工作(即您可以初始化和完成库或调用任何不直接访问相机的函数)。这似乎是 Java VM 遇到原生代码问题的情况,直接运行代码不会产生问题。您如何处理此类问题?这是我需要向制造商提出的问题,还是有处理此问题的配置/编译/链接方法?
一些额外的细节:
- Netbeans 6.9.1 开发环境
- JDK 1.7_0_03 64 位服务器
- 将源代码编译为 64 位(即不应存在 32 位与 64 位的问题)
【问题讨论】: