JNI "Ошибка поиска символа" в общей библиотеке в Linux - PullRequest
10 голосов
/ 05 марта 2012

Что вы делаете, когда Java VM имеет «ошибку поиска символа» при выполнении функции JNI?Ошибка поиска символа не в основной библиотеке общих объектов, поддерживающей интерфейс JNI, и не в самой библиотеке, связанной с библиотекой первичных объектов, а в библиотеке, которая связана с библиотекой, связанной с вашим общим объектом JNI?(что за невероятно неловкое предложение?) В частности, что вы делаете, если не управляете кодом для библиотеки, содержащей символ сбоя?

У меня проблема с использованием JNI для доступа к SDK для научногокамера (Андор NEO CMOS).Я использую плагин Netbeans C / C ++ на RHEL 6 для создания общей библиотеки (AndorC.so), которая в основном создает оболочки JNI для методов, предоставляемых камерами SDK.Camera SDK предоставляет набор методов для доступа к камере, которые упакованы в общую библиотеку объектов (libatcore.so).Библиотека libatcore.so использует ряд дополнительных библиотек: libatdevregcam.so (для реальной камеры), libatdevsimcam.so (для имитируемой камеры), libatcl_bitflow.so (низкоуровневый драйвер видеоплаты) и т. Д.

Я тщательно протестировал SDK камеры и без проблем могу получить доступ к камере из C / C ++.Я связался с общей библиотекой (AndorC), которая реализует функции JNI из тестовой программы C (с использованием отдельного файла заголовка), и все работает правильно (т.е. я могу прочитать изображение, и программа завершается нормально).

Мой Java-код может выполнять функции «InitializeLibrary» и «FinalizeLibrary» из SDK через интерфейс JNI, поэтому нет проблем с поиском первичной библиотеки 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 нет проблем с libatcore.so (то есть с файлом основной библиотеки), и у нее нет проблем с обнаружением связанной библиотеки времени выполнения (/ usr / local/lib/libatdevsimcam.so), но он сталкивается с неопределенным символом в этой библиотеке, когда пытается открыть камеру (обратите внимание, что я фактически открываю реальную камеру, а не имитируемую камеру).

Когда я проверял зависимости в каждой из библиотек (libAndorC.so, libatcore.so, libatdevsimcam.so), я не обнаружил каких-либо неопределенных символов.Очевидно, что неопределенный символ в библиотеке libatdevsimcam.so не является проблемой, когда программа запускается непосредственно из C / C ++, но вызывает проблему, когда виртуальная машина Java пытается загрузить 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, становится ясно, что символ не определен.

nm libatdevsimcam.so | grep _ZN20TAndor
             U _ZN20TAndorLibDebugOutput6OutputEPKciS1_xx24TAndorDebugFunctionLevel16TAndorDebugLevelS1_z

Я подумал, что, возможно, символ не был определенв выпускной и отладочной версии библиотеки libatdevsimcam.so, поэтому я попытался создать выпускную версию libAndorC.so, но у меня возникла та же проблема.

У меня есть два основных вопроса

  1. Может ли это быть проблемой с калечением имен в C ++?Я попытался скомпилировать мою программу тестирования камеры с помощью gcc вместо g ++, и я столкнулся с большим количеством ошибок компиляции.Я читал, что искажение имен в C ++ может вызвать проблемы.

  2. Это проблема в библиотеке libatdevsimcam.so, предоставленной производителем?Я не могу контролировать код, предоставленный Андором для поддержки камеры (все, что я могу сделать, это пожаловаться).

Я застрял на этом этапе, потому что все функции SDK требуют ссылки на дескриптор камеры, возвращаемый методом «Открыть».Если я не могу открыть камеру, я не могу приступить к разработке интерфейса JNI для камеры, которая мне нужна.

Я тщательно изучил этот вопрос и ненашел любые ответы, которые напрямую касаются проблемы. Это не стандартная ошибка «неудовлетворенная связь», которая так часто встречается в сообщениях JNI, и кажется, что базовые функции JNI работают (т.е. вы можете инициализировать и завершать работу библиотеки или вызывать любую функцию, которая не имеет прямого доступа к камере). Похоже, это ситуация, когда Java VM сталкивается с проблемой с собственным кодом, который просто не запускается при непосредственном запуске кода. Как вы справляетесь с такого рода проблемами? Это проблема, которую мне нужно отнести к производителю или есть метод конфигурации / компиляции / компоновки для решения этой проблемы?

Некоторые дополнительные сведения:

  • Среда разработки Netbeans 6.9.1
  • JDK 1.7_0_03 64-битный сервер
  • Компиляция исходников как 64-битных (то есть проблем не должно быть 32 против 64-битных)

Ответы [ 2 ]

12 голосов
/ 26 октября 2012

Вы можете избавиться от этого с помощью 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, как показано здесь , и сейчас решает проблему.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, не имеют никакого эффекта, поэтому я удален из компиляции.

EDIT-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

Для подробного ознакомления

Для подробного описания см. Эту книгу (или только этот поиск книг Google результат , @ ch.41.10)

5 голосов
/ 17 июня 2014

У меня была похожая проблема, и позже я обнаружил, что это проблема связывания порядка:

вам нужно поставить -L/usr/local/lib -lnetsnmp после -o libmytest.so, чтобы он заработал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...