2009-06-18 6 views
4

J'ai un programme Java qui appelle le code C via JNI que j'essaye de lancer sous Linux. Le code externe se compose de deux fichiers .so: un pour les liaisons JNI (construites avec swig) et l'autre avec les fonctions actuelles. J'ai les deux bibliothèques dans le même répertoire et LD_LIBRARY_PATH est correctement défini. ldd ne signale aucun problème lors de l'exécution à partir de la ligne de commande, mais lorsque je mets LD_LIBRARY_PATH à la même valeur dans la boîte de dialogue "Exécuter les configurations" de l'éditeur Eclipse et tente d'exécuter le programme, l'erreur suivante se produit:Comment déboguer une erreur java system.loadlibrary sous linux?

java .lang.UnsatisfiedLinkError: [chemin d'accès aux bibliothèques]/[bibliothèque de liaison JNI] .so: [bibliothèque de code actuelle] .so: impossible d'ouvrir le fichier d'objet partagé: aucun fichier ou répertoire

Ceci m'amène à croire que le JNI La bibliothèque wrapper est chargée avec succès, mais il y a un échec lorsque cette bibliothèque tente de charger la bibliothèque contenant le code réel. Y at-il un moyen de déboguer cela plus loin?

Je noterai en outre que ce problème se produit dans l'éditeur Eclipse lui-même et que je n'ai pas essayé de placer le code dans un fichier jar et de l'exécuter dans une instance jvm autonome.

Répondre

0

Vous pourriez essayer -Djava.library.path=actual.so dans les paramètres de ligne de commande peut-être?

Sous Windows, j'ai rencontré des problèmes similaires avec une bibliothèque tierce qui utilisait une DLL d'encapsuleur JNI pour ses DLL. Mon projet avait la DLL dans le répertoire lib donc j'ajouté lib au PATH (par exemple PATH=%PATH%;./lib variable d'environnement et, tout a commencé.

0

Pour autant que je sais que l'Eclipse n'utilise pas le LD_LIBRARY_PATH. La meilleure façon de définir le chemin de la bibliothèque native droite est d'aller à Propriétés du projet -> Java Build Path -> Bibliothèques Ensuite, développez l'entrée JRE System Library ou (si disponible) le fichier Jar qui utilise votre bibliothèque native, choisissez "Native Library" Emplacement "puis cliquez sur" Modifier ... "et choisissez le dossier dans lequel se trouvent vos bibliothèques. En fait, il définit la variable -Djava.library.path de sorte que vous devez l'inclure dans votre ligne de commande si vous démarrez votre programme depuis l'extérieur d'eclipse.

2

Je pense que le problème est avec l'appel à System.loadLibrary (String) et en utilisant LD_LIBRARY_PATH. L'utilisation de loadLibrary ("foo") recherchera dans votre fichier java.library.path quelque chose nommé libfoo.so. Si rien n'est nommé libfoo.so, vous obtiendrez cette erreur.

Maintenant, si vous venez de configurer LD_LIBRARY_PATH, les symboles natifs que vous voulez seront automatiquement récupérés par l'éditeur de liens, vous n'avez donc pas besoin de configurer -Djava.library.path. Dans mon expérience avec swig dans le projet gdal, cette erreur est en fait inoffensive et puisque le LD_LIBRARY_PATH est mis en place, cela fonctionnera bien. Je recommande d'utiliser -Djava.library.path et d'appeler explicitement loadLibrary, la raison étant que si vous décidez de déployer votre application avec webstart, vous devrez explicitement appeler loadLibrary pour récupérer vos bibliothèques natives. Lorsque j'utilise eclipse, je suis les instructions données par Daff lorsque vous éditez la bibliothèque native sous le pot dans l'onglet Bibliothèques du chemin de génération. Juste pour mentionner encore, ceci place juste java.library.path sous les couvertures.

0

Il se peut que vous ayez juste à trouver le bon endroit dans la boîte de dialogue de config run pour mettre l'option -Djava.library.path = ....Je pense que vous voulez -D définit dans les arguments "vm" sur l'onglet arguments, alors que si vous voulez définir LD_LIBRARY_PATH qui va sur l'onglet de l'environnement. Eclipse vous laissera joyeusement mettre des choses dans des endroits où ils ne veulent pas dire ce que vous pensez qu'ils veulent dire. Quoi qu'il en soit, j'ai utilisé des bibliothèques de cette façon auparavant et si j'ai l'occasion, je vais chercher ce que j'ai fait et éditer ma réponse ici.

Une autre chose à essayer est de jouer avec LD_DEBUG. Vous pouvez définir la variable d'environnement LD_DEBUG à diverses choses (essayez ALL), puis le chargeur Linux va divulguer toutes sortes d'informations utiles sur ce qu'une application essaie de charger, il cherche des choses, etc. Bien sûr, cela suppose que vous lancez eclipse à partir d'une ligne de commande, vous pouvez donc définir les variables d'env et voir les diagnostics du chargeur; mais en ce qui concerne le système, lorsque vous exécutez votre application depuis eclipse, votre application est juste quelque chose que fait Eclipse, donc tout comportement de chargement de bibliothèque peut être vu de cette manière.

0

Y a-t-il d'autres bibliothèques dont dépendent vos deux bibliothèques? Si c'est le cas, vous devez vous assurer qu'ils sont également accessibles à la JVM. Sachez que le réglage manuel de «-Djava.library.path» semble effacer le chemin de la bibliothèque par défaut.

Donc, avec le code suivant:

public class LibTest { 
    public static void main(String[] args) { 
     String property = System.getProperty("java.library.path"); 
     StringTokenizer parser = new StringTokenizer(property, ":"); 
     while (parser.hasMoreTokens()) { 
      System.err.println(parser.nextToken()); 
     } 
    } 
} 

Lancé depuis Eclipse avec Java 1.6.0_14 sorties:

/opt/java/jre/lib/i386/client 
/opt/java/jre/lib/i386 
/opt/java/jre/../lib/i386 
/opt/java/jre/lib/i386/client 
/opt/java/jre/lib/i386 
/usr/lib/xulrunner-devel-1.9.0.11 
/usr/lib/xulrunner-devel-1.9.0.11 
/usr/java/packages/lib/i386 
/lib 
/usr/lib 

Mais quand je mets la machine virtuelle Java arg « -Djava.library.path =/tmp/» Je n'obtenir:

/tmp/ 

Si vous configurez manuellement java.library.path cela peut expliquer pourquoi les travaux ldd de la commande l ine mais votre .so ne vient pas d'éclipse/java.

Vous pouvez essayer de ne pas définir java.library.path et utiliser System.load avec le chemin absolu de votre bibliothèque au lieu d'appeler System.loadLibrary. Cela peut permettre à la JVM de trouver votre fichier .so et d'utiliser le chemin par défaut lors de la recherche de ses dépendances.

Bien sûr, si cela ne sert à rien, vous pouvez également essayer d'activer la sortie de débogage jni avec "-verbose: jni" sur la ligne de commande. Cela peut vous donner des indices sur le problème.

0

Oui LD_LIBRARY_PATH a fonctionné pour moi

0

Ajoutant cette réponse est peut-être il peut être utile dans AIX Les machines dont nous avons besoin pour configurer la variable d'environnement LIBPATH au lieu de LD_LIBRARY_PATH.

Questions connexes