Comment réparer 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 cela dépend d’une bibliothèque tierce, libsndfile-1.dll.

Lorsque je lance mon programme, il se bloque avec

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

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

  1. J’ai couru des marcheurs de dépendances. DW a donné quelques avertissements – que deux bibliothèques requirejses par libsndfile, MPR.DLL et SHLWAPI.DLL, avaient des “importations non résolues” – mais la FAQ de DW a déclaré 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 des méthodes avaient été en quelque sorte effacés par le compilateur, mais j’ai ajouté des drapeaux de l’éditeur de liens et les noms des méthodes dll correspondent maintenant exactement à 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 – pour 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 fais mon développement dans Visual Studio 2010 sur un MacBook Pro (via Parallels). Je fais mes tests sous Windows XP sur un ordinateur portable Toshiba.

Je suis à peu près sûr que le chemin de classe et le chemin de recherche de la bibliothèque partagée ont peu à voir. Selon le JNI Book (qui est certes ancien), sous Windows, si vous n’utilisez pas la propriété système java.library.path , la DLL doit se trouver dans le répertoire de travail en cours ou dans un répertoire répertorié dans la variable d’environnement Windows PATH .


Mettre à jour:

Oracle semble avoir supprimé le PDF de son site Web. J’ai mis à jour le lien ci-dessus pour désigner une instance du PDF vivant à University of Texas – Arlington.

Vous pouvez également lire la version HTML d’Oracle de la spécification JNI . Cela vit dans la section Java 8 du site Web de Java et nous espérons que cela durera un moment.


Mise à jour 2:

Au moins dans Java 8 (je n’ai pas vérifié les versions précédentes), 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.

Je veux 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 pas sur Windows XP. Ensuite, j’utilise walker de dépendance et sur Windows XP, il n’y a pas d’exigence d’exécution de VC ++. Après avoir installé le package VC ++ Runtime, il fonctionne comme un charme. Ce qui me dérange, c’est qu’il n’arrête pas de trouver Ne trouve pas les bibliothèques dépendantes, alors que intuitivement la DLL dépendante de JNI est là, mais il s’avère que la DLL dépendante de JNI nécessite une autre dl dépendante. J’espère que ça aide.

Vous devez charger votre bibliothèque JNI.

System.loadLibrary charge la DLL à partir du chemin JVM (chemin du bac 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

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

Vous pouvez nommer java.library.path lors du lancement d’une application Java:

 java -Djava.library.path=path ... 

Vous avez eu un problème identique sur une machine XP lors de l’installation de javacv et opencv en combinaison 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.

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

J’avais exactement le même problème et finalement, le problème était résolu.

Je mets toutes les DLL dépendantes dans le même dossier où mylib.dll a été stocké et vérifie que le compilateur JAVA pourrait le trouver (s’il n’y a pas de mylib.dll dans le chemin de compilation, il y aurait une erreur lors de la compilation). La chose importante à noter est que vous devez vous assurer que toutes les bibliothèques dépendantes sont de la même version avec mylib.dll, par exemple si votre version de mylib.dll est la version, vous devez également y mettre 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.

J’ai eu le même problème et j’ai tout essayé, mais aucune n’a fonctionné pour moi. Dans mon cas, j’utilise Cygwin pour comstackr 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 de Cygwin aux DLL de JRE et cela fonctionne maintenant. J’ai fait quelque chose comme:

SET PATH = “/ cygdrive / c / Program Files / Java / jdk1.8.0_45”;% PATH%

Dans ma situation, j’essayais d’exécuter un service Web Java dans Tomcat 7 via un connecteur dans Eclipse. L’application a bien fonctionné 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 jdbc 2 pour “IBM DB2 9.5”. Pour une raison quelconque, le connecteur dans Eclispe n’a pas pu voir ou utiliser les chemins dans les variables d’environnement IBM DB2, pour accéder aux fichiers dll installés sur mon ordinateur portable en tant que client jcc. Le message d’erreur indique que le fichier db2jcct2 dll n’a pas pu être trouvé ou qu’il n’a pas réussi à trouver les bibliothèques dépendantes de ce fichier dll. Finalement, j’ai supprimé le connecteur et l’ai reconstruit. Ensuite, cela a fonctionné correctement. J’ajoute cette solution ici en tant que documentation, car je n’ai pas réussi à trouver cette solution spécifique ailleurs.

  • Réponse courte: pour l’erreur “impossible de trouver la bibliothèque dépendante”, vérifiez votre $ PATH (correspond à la puce n ° 3 ci-dessous)
  • Longue réponse:
    1. Pure java world: jvm utilise “Classpath” pour trouver des fichiers de classe
    2. Monde JNI (java / limite native): jvm utilise “java.library.path” (qui par défaut est $ PATH) pour trouver dlls
    3. monde natif pur: le code natif utilise $ PATH pour charger d’autres dll

J’ai trouvé un excellent article par des amis à 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! Lire si vous êtes intéressé ( Les dangers du chargement des bibliothèques natives sur Android ) ou simplement utiliser

comstack 'com.getkeepsafe.relinker:relinker:1.2.3'

et remplacer

 System.loadLibrary("myLibrary"); 

avec

 ReLinker.loadLibrary(context, "mylibrary"); 
  1. Allez à http://tess4j.sourceforge.net/usage.html et cliquez sur Visual C++ Redissortingbutable for VS2012
  2. Téléchargez-le et exécutez VSU_4\vcredist_x64.exe ou VSU_4\vcredist_x84.exe fonction de la configuration de votre système.
  3. Placez vos fichiers dll dans le dossier lib , avec vos autres bibliothèques (par exemple, \lib\win32-x86\your dll files ).