JNI“符号查找错误"在Linux上的共享库中 [英] JNI "symbol lookup error" in shared library on Linux

查看:59
本文介绍了JNI“符号查找错误"在Linux上的共享库中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当执行JNI函数时Java VM出现符号查找错误"时,您该怎么办?符号查找错误不是在支持JNI接口的主要共享对象库中,也不是在直接链接至主要对象库的库中,而是在链接至与您的JNI共享对象链接的库的库中? (这是一个令人尴尬的句子☺)特别是,当您不控制包含令人讨厌的符号的库的代码时,该怎么办?

What do you do when the Java VM has a "symbol lookup error" when executing a JNI function? The symbol lookup error is not in the primary shared object library that support the JNI interface, nor is it directly within a library linked to the primary object library, but in a library that’s linked to a library that’s linked to your JNI shared object? (what an incredibly awkward sentence ☺) Particularly, what do you do when you don’t control the code for the library that contains the offending symbol?

我在使用JNI访问用于科学相机(或NEO CMOS)的SDK时遇到问题.我正在RHEL 6上使用Netbeans C/C ++插件来创建一个共享库(AndorC.so),该库基本上围绕相机SDK提供的方法创建JNI包装器.相机SDK提供了一组访问相机的方法,这些方法打包在共享对象库(libatcore.so)中. libatcore.so库使用一系列附加库,如libatdevregcam.so(用于真实相机),libatdevsimcam.so(用于模拟相机),libatcl_bitflow.so(低级视频板驱动程序)等.

I have a problem using JNI to access the SDK for a scientific camera (Andor NEO CMOS). I’m using the Netbeans C/C++ plugin on RHEL 6 to create a shared library (AndorC.so) that basically creates JNI wrappers around the methods provided by the cameras SDK. The camera SDK provides a set of methods to access the camera, which are packaged in a shared object library (libatcore.so). The libatcore.so library uses a series of additional libraries, libatdevregcam.so (for the real camera), libatdevsimcam.so (for the simulated camera), libatcl_bitflow.so (low level video board driver), etc. .

我已经对相机SDK进行了广泛的测试,并且可以从C/C ++轻松访问相机.我已链接到共享库(AndorC),该库从测试C程序(使用单独的头文件)实现JNI功能,并且一切正常运行(即,我可以读取图像并且程序正常完成).

I have tested the camera SDK extensively and I can access the camera with no difficulty from C/C++. I have linked to the shared library (AndorC) that implements the JNI functions from a test C program (using a separate header file) and everything runs properly (i.e. I can read an image and the program completes normally).

我的Java代码可以通过JNI接口从SDK执行"InitializeLibrary"和"FinalizeLibrary"功能,因此找到主libatcore.so库或我的AndorC.so库没有问题. JNI的基本设置似乎没有任何问题.但是,当我尝试为相机执行打开"功能(即实际上连接到真实和/或模拟相机的功能)时,在libatcore.so库在以下位置使用的一个库中出现未定义的符号错误.运行时(libdevsimcam.so).

My Java code can execute the "InitializeLibrary" and "FinalizeLibrary" functions from the SDK through the JNI interface so there is no problem finding the primary libatcore.so library or my AndorC.so library. There doesn’t appear to be any problem with the basic setup of the JNI. However, when I try to execute the "Open" function for the camera (i.e. the function that actually connects to the real and/ or simulated camera) I get an undefined symbol error in one of the libraries that the libatcore.so libraries uses at runtime (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) ),但在尝试打开相机时会在该库中遇到一个未定义的符号(请注意,我实际上是在打开真实相机,而不是模拟相机).

Essentially, the Java VM doesn’t have a problem with the libatcore.so (i.e. the main library file) and it doesn’t have a problem locating the associated runtime library (/usr/local/lib/libatdevsimcam.so) but it runs into an undefined symbol in that library when it tries to open the camera (note I’m actually opening the real camera NOT the simulated camera).

当我检查每个库(libAndorC.so,libatcore.so,libatdevsimcam.so)的依赖性时,我没有找到任何未定义的符号.显然,当直接从C/C ++运行程序时,libatdevsimcam.so库中的未定义符号不是问题,但是当Java VM尝试加载libatdevsimcam.so时,这会引起问题.

When I checked the dependencies on each of the libraries (libAndorC.so, libatcore.so, libatdevsimcam.so) I don’t find any undefined symbols. Obviously, the undefined symbol in the libatdevsimcam.so library isn’t a problem when the program is run directly from C/C++ but it’s causing a problem when the Java VM tries to load 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出现问题的符号时,很明显该符号未定义.

When I specifically check the symbol that the Java VM is having a problem with it’s clear that the symbol is undefined.

nm libatdevsimcam.so | grep _ZN20TAndor
             U _ZN20TAndorLibDebugOutput6OutputEPKciS1_xx24TAndorDebugFunctionLevel16TAndorDebugLevelS1_z

我以为libatdevsimcam.so库的发行版与调试版中未定义符号,所以我尝试构建libAndorC.so的发行版,但遇到了同样的问题.

I thought perhaps the symbol wasn’t defined in the release vs. debug version of the libatdevsimcam.so library so I tried building a release version of the libAndorC.so but I got the same problem.

我有两个基本问题

  1. 这可能是C ++名称修改的问题吗?我尝试用gcc而不是g ++编译我的相机测试程序,但遇到了很多编译错误.我已经读过C ++名称修饰会导致问题.

  1. Could this be a problem with C++ name mangling? I’ve tried compiling my camera test program with gcc instead of g++ and I run into a large number of compilation errors. I’ve read that C++ name mangling can cause problems.

制造商提供的libatdevsimcam.so库是否有问题?我无法控制由Andor提供的支持相机的代码(我所能做的就是抱怨).

Is this a problem in the libatdevsimcam.so library provided by the manufacturer? I have no control over the code supplied by Andor to support the camera (all I can do is complain).

由于所有SDK函数都需要引用"Open"方法返回的摄像头句柄,因此我基本上会停留在这一点上.如果无法打开相机,则无法继续开发所需相机的JNI界面.

I’m basically stuck at this point because all of the SDK functions require a reference to the camera handle returned by the "Open" method. If I can’t open the camera I can’t proceed with developing the JNI interface to the camera that’s I need.

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

I’ve research this question extensively and I haven’t found any answers that directly address the issue. This isn’t the standard "unsatisfied link" error that’s so common in JNI posts and the basic JNI functionality seems to work (i.e. you can initialize and finalize the library or call any function that doesn’t directly access the camera) . This seems to be a situation where the Java VM runs into a problem with the native code that simply running the code directly doesn’t produce. How do you deal with this kind of issue? Is this a problem I need to take to the manufacturer or is there a configuration / compilation / linking method of dealing with this?

一些其他详细信息:

  • Netbeans 6.9.1开发环境
  • JDK 1.7_0_03 64位服务器
  • 将源代码编译为64位(即应该没有32位和64位问题)

推荐答案

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

You can get rid of it by using LD_PRELOAD (but i don't think this is a proper solution)

故事

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

I faced the same problem, and my scenario is...

* javaHelloWorldApp.java-> JNI_Hello_world.c->此本地c函数调用snmp库*

*javaHelloWorldApp.java --> JNI_Hello_world.c --> this native c function calls to snmp library*

java: symbol lookup error: /home/source/bin/libmytest.so: undefined symbol: init_snmp

我使用了LD_PRELOAD,如此处所示,并已解决了该问题. export LD_PRELOAD=/usr/local/lib/libnetsnmp.so.30

I used LD_PRELOAD as shown here and solves the problem for now. export LD_PRELOAD=/usr/local/lib/libnetsnmp.so.30

悬而未决的问题

ldd提供,(请注意,没有引用snmp库)

ldd gives, (note, there is no reference to snmp library)

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)

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的引用

with export LD_PRELOAD=/usr/local/lib/libnetsnmp.so.30 I see the references to snmp,

snmp $ ldd ../libredsnmp/bin/libredsnmp.so

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没有任何效果,所以我从编译中删除了.

Other options i tried, -L/usr/local/lib -lnetsnmp, doesn't have any effect so i removed from compilation.

EDIT-1

它可以与这两个命令一起使用,而没有其他环境变量, 首先,编译源代码

got it worked with these two commands and no other environment variable, First, compile the source

gcc -c -fPIC ./mytest.c -o mytest.o -I$(JAVA_INC_PATH) -I$(JAVA_INC_PATH)linux

现在,在构建共享库时使用-rpath链接器选项.

Now, use -rpath linker option when building the shared library.

gcc -shared -o ./bin/libmytest.so  mytest.o -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lnetsnmp

详细参考

有关详细说明,请参阅此(或仅对此Google图书进行搜索

For a detailed description refer this book (or just this google book search result, @ ch.41.10)

这篇关于JNI“符号查找错误"在Linux上的共享库中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆