gpt4 book ai didi

java-native-interface - Linux 上共享库中的 JNI "symbol lookup error"

转载 作者:行者123 更新时间:2023-12-04 03:09:11 27 4
gpt4 key购买 nike

Java VM 在执行 JNI 函数时出现“符号查找错误”怎么办?符号查找错误不在支持 JNI 接口(interface)的主要共享对象库中,也不直接在链接到主要对象库的库中,而是在链接到链接到 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 接口(interface)从 SDK 执行“InitializeLibrary”和“FinalizeLibrary”函数,因此找到主要的 libatcore.so 库或我的 AndorC.so 库没有问题。 JNI 的基本设置似乎没有任何问题。但是,当我尝试为相机执行“打开”功能(即实际连接到真实和/或模拟相机的功能)时,我在 libatcore.so 库使用的库之一中收到 undefined symbol 错误运行时(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) 也没有问题,但它当它尝试打开相机时,在该库中遇到一个 undefined symbol (请注意,我实际上是在打开真实相机而不是模拟相机)。

当我检查每个库(libAndorC.so、libatcore.so、libatdevsimcam.so)的依赖关系时,我没有找到任何 undefined symbol 。显然,当程序直接从 C/C++ 运行时,libatdevsimcam.so 库中的 undefined symbol 不是问题,但是当 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 接口(interface)。

    我对这个问题进行了广泛的研究,但没有找到任何直接解决这个问题的答案。这不是 JNI 帖子中常见的标准“不满意链接”错误,而且基本的 JNI 功能似乎可以工作(即您可以初始化和完成库或调用任何不直接访问相机的函数)。这似乎是 Java VM 遇到原生代码问题,直接运行代码不会产生的问题。您如何处理此类问题?这是我需要向制造商提出的问题还是有解决此问题的配置/编译/链接方法?

    一些额外的细节:
  • Netbeans 6.9.1 开发环境
  • JDK 1.7_0_03 64 位服务器
  • 将源代码编译为 64 位(即应该没有 32 位与 64 位的问题)
  • 最佳答案

    您可以通过使用 LD_PRELOAD 来摆脱它(但我认为这不是一个合适的解决方案)

    故事

    我遇到了同样的问题,我的情况是......

    *javaHelloWorldApp.java --> JNI_Hello_world.c --> 这个原生的c 函数调用snmp 库*
    java: symbol lookup error: /home/source/bin/libmytest.so: undefined symbol: init_snmp
    我使用了 LD_PRELOAD,如图所示 here并暂时解决问题。export LD_PRELOAD=/usr/local/lib/libnetsnmp.so.30
    未解决问题

    ldd 给出,(注意,没有对 snmp 库的引用)

    ldd ../libmytest/bin/libmytest.so linux-gate.so.1 => (0xb7777000) libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75a3000) /lib/ld-linux.so.2 (0xb7778000)



    export LD_PRELOAD=/usr/local/lib/libnetsnmp.so.30我看到了对 snmp 的引用,

    snmp$ldd ../libredsnmp/bin/libredsnmp.so
    linux-gate.so.1 =>  (0xb770c000)
    /usr/local/lib/libnetsnmp.so.30 (0xb763a000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb746c000)
    librt.so.1 => /lib/i386-linux-gnu/librt.so.1 (0xb7462000)
    libcrypto.so.1.0.0 => /lib/i386-linux-gnu/libcrypto.so.1.0.0 (0xb72b7000)
    /lib/ld-linux.so.2 (0xb770d000)
    libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb729c000)
    libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0xb7297000)
    libz.so.1 => /lib/i386-linux-gnu/libz.so.1 (0xb7281000)

    我的编译行,
    gcc -fPIC -shared -o ./bin/libmytest.so -I/usr/lib/jvm/java-6-openjdk-i386/include/ -I/usr/lib/jvm/java-6-openjdk-i386/include/linux -static -lc JNI_Hello_world.c
    我尝试过的其他选项, -L/usr/local/lib -lnetsnmp , 没有任何影响,所以我从编译中删除。

    编辑-1

    让它与这两个命令一起工作,没有其他环境变量,
    一、编译源码
    gcc -c -fPIC ./mytest.c -o mytest.o -I$(JAVA_INC_PATH) -I$(JAVA_INC_PATH)linux

    现在,在构建共享库时使用 -rpath 链接器选项。
    gcc -shared -o ./bin/libmytest.so  mytest.o -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lnetsnmp

    详细引用

    有关详细说明,请参阅此 book (或者只是这个谷歌图书搜索 result,@ ch.41.10)

    关于java-native-interface - Linux 上共享库中的 JNI "symbol lookup error",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9558909/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com