JNI "Symbolsuchfehler" in der gemeinsam genutzten Bibliothek unter Linux

9

Was tun Sie, wenn die Java-VM beim Ausführen einer JNI-Funktion einen "Symbolsuchfehler" aufweist? Der Symbolsuchfehler befindet sich nicht in der primären gemeinsamen Objektbibliothek, die die JNI-Schnittstelle unterstützt, noch direkt in einer mit der primären Objektbibliothek verknüpften Bibliothek, sondern in einer Bibliothek, die mit einer Bibliothek verknüpft ist, die mit Ihrem gemeinsamen JNI-Objekt verknüpft ist? (Was für ein unglaublich peinlicher Satz ☺) Was tun Sie besonders, wenn Sie den Code für die Bibliothek, die das anstößige Symbol enthält, nicht kontrollieren?

Ich habe ein Problem mit JNI, um auf das SDK für eine wissenschaftliche Kamera (Andor NEO CMOS) zuzugreifen. Ich verwende das Netbeans C / C ++ - Plugin auf RHEL 6, um eine gemeinsam genutzte Bibliothek (AndorC.so) zu erstellen, die im Grunde JNI-Wrapper um die vom SDK der Kameras bereitgestellten Methoden erstellt. Das Kamera-SDK bietet eine Reihe von Methoden für den Zugriff auf die Kamera, die in einer gemeinsamen Objektbibliothek (libatcore.so) enthalten sind. Die libatcore.so-Bibliothek verwendet eine Reihe von zusätzlichen Bibliotheken, libatdevregcam.so (für die echte Kamera), libatdevsimcam.so (für die simulierte Kamera), libatcl_bitflow.so (Low-Level-Grafikkartentreiber) usw.

Ich habe das Kamera-SDK ausgiebig getestet und kann problemlos von C / C ++ auf die Kamera zugreifen. Ich habe mit der gemeinsamen Bibliothek (AndorC) verbunden, die die JNI-Funktionen von einem Test-C-Programm implementiert (mit einer separaten Header-Datei) und alles ordnungsgemäß ausgeführt wird (d. H. Ich kann ein Bild lesen und das Programm wird normal abgeschlossen).

Mein Java-Code kann die Funktionen "InitializeLibrary" und "FinalizeLibrary" vom SDK über die JNI-Schnittstelle ausführen, so dass es kein Problem gibt, die primäre libatcore.so-Bibliothek oder meine AndorC.so-Bibliothek zu finden. Es scheint keine Probleme mit der grundlegenden Einrichtung des JNI zu geben. Wenn ich jedoch versuche, die Funktion "Öffnen" für die Kamera auszuführen (dh die Funktion, die tatsächlich mit der realen und / oder simulierten Kamera verbunden ist), erhalte ich einen undefinierten Symbolfehler in einer der Bibliotheken, die die libatcore.so-Bibliotheken verwenden Laufzeit (libdevsimcam.so).

%Vor%

Im Wesentlichen hat die Java-VM kein Problem mit der libatcore.so (dh der Hauptbibliotheksdatei) und es hat kein Problem, die zugehörige Laufzeitbibliothek (/usr/local/lib/libatdevsimcam.so) zu finden ) aber es läuft in ein undefiniertes Symbol in dieser Bibliothek, wenn es versucht, die Kamera zu öffnen (beachte, dass ich tatsächlich die echte Kamera öffne, NICHT die simulierte Kamera).

Wenn ich die Abhängigkeiten für jede der Bibliotheken überprüft habe (libAndorC.so, libatcore.so, libatdevsimcam.so), finde ich keine undefinierten Symbole. Offensichtlich ist das undefinierte Symbol in der libatdevsimcam.so-Bibliothek kein Problem, wenn das Programm direkt von C / C ++ ausgeführt wird, aber es verursacht ein Problem, wenn die Java-VM versucht, libatdevsimcam.so zu laden.

%Vor%

Wenn ich speziell das Symbol überprüfe, dass die Java VM ein Problem hat, ist klar, dass das Symbol nicht definiert ist.

%Vor%

Ich dachte, das Symbol sei vielleicht nicht in der Release- oder Debug-Version der libatdevsimcam.so-Bibliothek definiert, also habe ich versucht, eine Release-Version von libAndorC.so zu erstellen, aber ich habe das gleiche Problem.

Ich habe zwei grundlegende Fragen

  1. Könnte das ein Problem mit C ++ - Namensfehlern sein? Ich habe versucht, mein Kameratestprogramm mit gcc anstelle von g ++ zu kompilieren, und ich lief auf eine große Anzahl von Kompilierungsfehlern. Ich habe gelesen, dass die C ++ - Namensänderung Probleme verursachen kann.

  2. Ist das ein Problem in der Bibliothek libatdevsimcam.so des Herstellers? Ich habe keine Kontrolle über den von Andor gelieferten Code zur Unterstützung der Kamera (ich kann mich nur beschweren).

Ich stehe im Grunde an diesem Punkt fest, weil alle SDK-Funktionen einen Verweis auf das von der "Öffnen" -Methode zurückgegebene Kamera-Handle benötigen. Wenn ich die Kamera nicht öffnen kann, kann ich nicht mit der Entwicklung der JNI-Schnittstelle zu der Kamera fortfahren, die ich brauche.

Ich habe diese Frage ausführlich untersucht und ich habe keine Antworten gefunden, die das Problem direkt ansprechen. Dies ist nicht der Standardfehler "Unbefriedigter Link", der in JNI-Posts so häufig vorkommt, und die grundlegende JNI-Funktionalität scheint zu funktionieren (d. H. Sie können die Bibliothek initialisieren und finalisieren oder eine Funktion aufrufen, die nicht direkt auf die Kamera zugreift). Dies scheint eine Situation zu sein, in der die Java-VM auf ein Problem mit dem systemeigenen Code stößt, das durch einfaches Ausführen des Codes nicht direkt erzeugt wird. Wie gehst du mit dieser Art von Problem um? Ist das ein Problem, das ich an den Hersteller stellen muss, oder gibt es eine Konfigurations- / Kompilierungs- / Verknüpfungsmethode?

Einige zusätzliche Details:

  • Netbeans 6.9.1 Entwicklungsumgebung
  • JDK 1.7_0_03 64-Bit-Server
  • Kompilieren von Quellen als 64 Bit (d. h. es sollte keine 32 vs 64 Bit Probleme geben)
Jennifer Milburn 04.03.2012, 21:19
quelle

2 Antworten

10

Sie können es loswerden, indem Sie LD_PRELOAD verwenden (aber ich denke nicht, dass dies eine richtige Lösung ist)

Die Geschichte

Ich hatte das gleiche Problem und mein Szenario ist ...

* javaHelloWorldApp.java - & gt; JNI_Hello_world.c - & gt; Diese native c-Funktion ruft die snmp-Bibliothek *

auf

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

Ich habe LD_PRELOAD wie hier gezeigt hier verwendet und löst das Problem für den Moment. export LD_PRELOAD=/usr/local/lib/libnetsnmp.so.30

Frage öffnen

ldd gibt (beachte, dass es keine Referenz auf die snmp-Bibliothek gibt)

  

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

mit export LD_PRELOAD=/usr/local/lib/libnetsnmp.so.30 Ich sehe die Verweise auf snmp,

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

%Vor%

meine Kompilierungszeile,

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

Andere Optionen, die ich ausprobiert habe, -L/usr/local/lib -lnetsnmp , hat keinen Effekt, also habe ich die Kompilierung entfernt.

EDIT-1

hat es funktioniert mit diesen beiden Befehlen und keine andere Umgebungsvariable, Kompilieren Sie zuerst die Quelle

%Vor%

Verwenden Sie jetzt die Option -rpath linker beim Erstellen der gemeinsam genutzten Bibliothek.

%Vor%

Detaillierte Referenz

Eine ausführliche Beschreibung finden Sie in diesem Buch (oder nur in dieser Google Buchsuche Ergebnis , @ ch.41.10)

    
tsenapathy 26.10.2012 11:24
quelle
4

Ich hatte ein ähnliches Problem, und später stellte ich fest, dass es das Problem der Verknüpfungsreihenfolge war:

Sie müssen -L/usr/local/lib -lnetsnmp nach dem -o libmytest.so setzen, damit es funktioniert.

    
tudali0928 17.06.2014 07:10
quelle

Tags und Links