web-dev-qa-db-fra.com

Comment réparer une UnsatisfiedLinkError (Impossible de trouver des bibliothèques dépendantes) dans un projet JNI

Je travaille sur un projet Java qui utilise le JNI. JNI appelle une bibliothèque personnalisée que j'ai moi-même écrite, disons mylib.dll, et qui dépend d'une bibliothèque tierce, libsndfile-1.dll.

Quand je lance mon programme, il plante

Java.lang.UnsatisfiedLinkError:  C:\...path...\mylib.dll: Can't find dependent libraries.

J'ai effectué des recherches sur ce site (et d'autres) et j'ai essayé plusieurs correctifs:

  1. J'ai couru la dépendance walker. DW a averti deux fois que deux bibliothèques requises par libsndfile, MPR.DLL et SHLWAPI.DLL, avaient des "importations non résolues" - mais la DW FAQ indiquait que ces avertissements pouvaient être ignorés en toute sécurité.

  2. J'ai corrigé les noms de méthodes dans mylib.dll, comme suggéré ici . Les noms de méthodes avaient en quelque sorte été endommagés par le compilateur, mais j’ai ajouté des indicateurs de lieur et les noms de méthodes dll correspondent maintenant à ceux de mon fichier d’en-tête jni.

  3. Je mets toutes ces DLL dans le même répertoire - le même répertoire que le fichier .jar qui les appelle - afin de s’assurer qu’elles se trouvent sur le bon PATH.

Pas de dé.

Est-ce que quelqu'un a une idée de ce qui se passe?

Je suis en train de développer Visual Studio 2010 sur un MacBook Pro (via Parallels). Je fais mes tests sous Windows XP sur un ordinateur portable Toshiba.

74
dB'

Je suis à peu près sûr que le classpath et le chemin de recherche de la bibliothèque partagée ont peu à voir l'un avec l'autre. Selon The JNI Book (qui est certes ancien), sous Windows, si vous n'utilisez pas la propriété système Java.library.path, la DLL doit être dans le mode de fonctionnement actuel. répertoire ou dans un répertoire répertorié dans la variable d’environnement Windows PATH.


Mise à jour:

On dirait que Oracle a supprimé le PDF de son site Web. J'ai mis à jour le lien ci-dessus pour qu'il pointe vers un exemple de PDF résidant à l'Université du Texas - Arlington.

En outre, vous pouvez également lire la version HTML d'Oracle du Spécification JNI . Cela se trouve dans la section Java 8 du site Web Java et, espérons-le, sera là pendant un moment.


Mise à jour 2:

Au moins dans Java 8 (je n'ai pas vérifié les versions précédentes), vous pouvez effectuer les opérations suivantes:

Java -XshowSettings:properties -version

pour trouver le chemin de recherche de la bibliothèque partagée. Recherchez la valeur de la propriété Java.library.path dans cette sortie.

46
QuantumMechanic

Je tiens à informer ce cas intéressant, après avoir essayé toutes les méthodes ci-dessus, l'erreur est toujours là. La chose étrange est que cela fonctionne sur un ordinateur Windows 7, mais sur Windows XP ce n'est pas. Ensuite, j'utilise la dépendance walker trouvée sur Windows XP, il n'y a pas d'exécution VC++ comme condition requise pour la dll. Après avoir installé le paquet VC++ Runtime ici cela fonctionne à merveille. Ce qui m’a dérangé, c’est qu’il continue de dire que je ne trouve pas de bibliothèques dépendantes, alors que intuitivement la dll dépendante de JNI est présente, mais qu’elle finit par s'avérer que la dll dépendante de JNI nécessite une autre dl dépendante. J'espère que ça aide.

17
longbkit

Vous devez charger votre bibliothèque JNI.

System.loadLibrary charge le DLL à partir du chemin de la JVM (chemin de la corbeille JDK).

Si vous voulez charger un fichier explicite avec un chemin, utilisez System.load ()

Voir aussi: Différence entre System.load () et System.loadLibrary en Java

13
Yochai Timmer

Veuillez vérifier si le chemin de votre bibliothèque est correct ou non. Bien sûr, vous pouvez utiliser le code suivant pour vérifier le chemin du chemin de la bibliothèque: System.out.println(System.getProperty("Java.library.path"));

Vous pouvez désigner le Java.library.path lors du lancement d'une application Java:

Java -Djava.library.path=path ...
5
caopeng

Avait un problème identique avec la machine XP lors de l’installation de javacv et opencv en association avec Eclipse. Il s'est avéré qu'il me manquait les fichiers suivants:

  • msvcp100.dll
  • msvcr100.dll

Une fois ceux-ci installés, le projet a été compilé et exécuté correctement.

4
Rob van Riswick

Si vous chargez une version 32 bits de votre dll avec un JRE 64 bits, vous risquez d'avoir ce problème. C'était mon cas.

4
EFalco
  • Réponse courte: pour l'erreur "ne trouve pas la bibliothèque dépendante", vérifiez votre $ PATH (correspond au point # 3 ci-dessous)
  • Longue réponse:
    1. Pure Java world: jvm utilise "Classpath" pour rechercher les fichiers de classe
    2. Monde JNI (limite Java/native): jvm utilise "Java.library.path" (par défaut, $ PATH) pour rechercher des dll
    3. monde natif pur: le code natif utilise $ PATH pour charger d'autres dll
2
user2038596

J'ai trouvé un article formidable rédigé par des amis de Keepafe qui a vécu la même chose que moi. Cela a fonctionné pour moi, alors j'espère que cela vous aidera aussi! Ayez une lecture si vous êtes intéressé ( Les dangers de charger des bibliothèques natives sur Android ) ou utilisez simplement

compile 'com.getkeepsafe.relinker:relinker:1.2.3'

et remplacer

System.loadLibrary("myLibrary");

avec

ReLinker.loadLibrary(context, "mylibrary");
2
rhysl

Dans ma situation, j’essayais d’exécuter un service Web Java dans Tomcat 7 via un connecteur dans Eclipse. L'application fonctionnait bien lorsque j'ai déployé le fichier war sur une instance de Tomcat 7 sur mon ordinateur portable. L'application nécessite un pilote de type 2 jdbc pour "IBM DB2 9.5". Pour une raison quelconque, le connecteur dans Eclispe n'a pas pu voir ou utiliser les chemins des variables d'environnement IBM DB2 pour atteindre les fichiers dll installés sur mon ordinateur portable en tant que client jcc. Le message d'erreur indique soit qu'il n'a pas réussi à trouver le fichier dll db2jcct2, soit qu'il n'a pas trouvé les bibliothèques dépendantes de ce fichier dll. Finalement, j'ai supprimé le connecteur et je l'ai reconstruit. Ensuite, cela a fonctionné correctement. J'ajoute cette solution ici en tant que documentation, car je n'ai pas trouvé cette solution spécifique ailleurs.

1
bwfrieds

J'ai eu le même problème, et j'ai essayé tout ce qui est posté ici pour le réparer, mais aucun n'a fonctionné pour moi. Dans mon cas, j'utilise Cygwin pour compiler la DLL. Il semble que JVM tente de trouver les DLL JRE dans le chemin Cygwin virtuel. J'ai ajouté le chemin du répertoire virtuel du Cygwin aux DLL de JRE et cela fonctionne maintenant. J'ai fait quelque chose comme:

SET PATH = "/ cygdrive/c/Fichiers de programme/Java/jdk1.8.0_45";% PATH%

1
estebanuri

J'avais exactement le même problème et finalement, il a été résolu.

Je mets toutes les DLL dépendantes dans le même dossier que mylib.dll et en veillant à ce que le compilateur Java puisse le trouver (s'il n'y a pas mylib.dll dans le chemin de compilation, il y aura une erreur signalée ceci pendant la compilation). La chose importante à noter est que vous devez vous assurer que toutes les bibliothèques dépendantes ont la même version que mylib.dll. Par exemple, si votre fichier mylib.dll est une version, vous devez également y placer la version de toutes ses bibliothèques dépendantes. .

J'espère que cela pourrait aider d'autres personnes qui ont rencontré le même problème.

1
Steven Peng

installation de Microsoft Visual C++ 2010 SP1 redistribuable corrigée

0
Sunil Kumar

Créer une bibliothèque statique a fonctionné pour moi, compiler avec g++ -static. Il regroupe les bibliothèques dépendantes avec la construction.

0
Caesar