101 votes

Comment corriger une UnsatisfiedLinkError (Impossible de trouver les bibliothèques dépendantes) dans un projet JNI

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

Lorsque je lance mon programme, il plante avec

java.lang.UnsatisfiedLinkError:  C:\...chemin...\mylib.dll: Impossible de trouver les bibliothèques dépendantes.

J'ai cherché sur ce site (et d'autres) et j'ai essayé un certain nombre de solutions :

  1. J'ai exécuté Dependency Walker. DW a donné quelques avertissements -- que deux bibliothèques requises par libsndfile, MPR.DLL et SHLWAPI.DLL, avaient des "imports non résolus" -- mais la FAQ de DW disait que ces avertissements pouvaient être ignorés en toute sécurité.

  2. J'ai corrigé les noms de méthode dans mylib.dll, comme suggéré ici. Les noms de méthode avaient été malmenés par le compilateur, mais j'ai ajouté des drapeaux de liaison et les noms de méthode du dll correspondent maintenant exactement à ceux de mon fichier d'en-tête jni.

  3. J'ai mis tous ces DLL dans le même répertoire -- le même répertoire que le .jar qui les appelle -- pour m'assurer qu'ils sont sur le bon CHEMIN.

Ça ne marche pas.

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

Je développe dans Visual Studio 2010 sur un MacBook pro (via Parallels). Je fais mes tests sous Windows XP sur un ordinateur portable toshiba.

64voto

QuantumMechanic Points 7825

Je suis assez sûr que le chemin de classe et le chemin de recherche de la bibliothèque partagée n'ont que peu de chose en commun. Selon The JNI Book (qui est certes ancien), sur Windows, si vous n'utilisez pas la propriété système java.library.path, le DLL doit être dans le répertoire de travail actuel ou dans un répertoire répertorié dans la variable d'environnement Windows PATH.


Mise à jour:

Il semblerait qu'Oracle ait supprimé le PDF de son site web. J'ai mis à jour le lien ci-dessus pour pointer vers une instance du PDF disponible à l'Université du Texas - Arlington.

De plus, vous pouvez également consulter la version HTML de la Spécification JNI d'Oracle. Cela se trouve dans la section Java 8 du site web de Java et devrait donc être disponible pendant un certain temps.


Mise à jour 2:

Au moins dans Java 8 (je n'ai pas vérifié les versions antérieures), vous pouvez faire :

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.

23voto

longbkit Points 382

Je veux informer de ce cas intéressant, après avoir essayé toutes les méthodes ci-dessus, l'erreur est toujours là. La chose étrange est que ça marche sur un ordinateur Windows 7, mais pas sur Windows XP. Ensuite, j'ai utilisé dependency walker et j'ai trouvé que sur Windows XP il n'y avait pas de VC++ Runtime comme requis par mon dll. Après avoir installé le package VC++ Runtime ici, ça fonctionne comme un charme. Ce qui m'a troublé, c'est qu'il continue de dire qu'il ne trouve pas les bibliothèques dépendantes, alors qu'intuitivement le dll dépendant JNI est là, mais finalement il s'avère que le dll dépendant JNI nécessite un autre dll dépendant. J'espère que cela aidera.

15voto

Yochai Timmer Points 19802

Vous devez charger votre bibliothèque JNI.

System.loadLibrary charge le DLL depuis le chemin du JVM (JDK bin path).

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

12voto

EFalco Points 365

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

6voto

Region39 Points 145

Lors de l'appel à System.loadLibrary(), le JVM recherchera votre bibliothèque native sur le java.library.path. Cependant, si cette bibliothèque native déclare des dépendances avec d'autres bibliothèques natives, alors c'est le système d'exploitation qui sera chargé de trouver ces dépendances de bibliothèque natives.

Comme le système d'exploitation n'a pas de concept du java.library.path, il ne verra pas les répertoires que vous placez sur le java.library.path. Au lieu de cela, il ne recherchera que les répertoires sur la variable d'environnement PATH du système d'exploitation. C'est tout à fait normal si la dépendance de bibliothèque native est une bibliothèque native du système d'exploitation car elle sera trouvée sur la PATH. Cependant, si la dépendance de bibliothèque native est une bibliothèque native que vous ou quelqu'un d'autre avez créée, alors elle ne sera pas trouvée sur la PATH à moins que vous ne la placiez là. Ce comportement est étrange, inattendu et pas bien documenté, mais il est documenté dans le suivi des problèmes d'OpenJDK ici. Vous pouvez également trouver une autre réponse de StackOverflow renforçant cette explication, ici.

Donc, vous avez quelques options. Vous pourriez charger chaque bibliothèque native dans l'ordre de dépendance correct en utilisant System.loadLibrary(), ou vous pourriez modifier la PATH pour inclure les répertoires où vos bibliothèques natives sont stockées.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X