100 votes

java.lang.UnsatisfiedLinkError no *****. dll dans java.library.path

Comment puis-je charger un fichier dll personnalisé dans mon application Web? J'ai essayé de suivre les moyens mais son échec.

  • copié toutes les dll requises dans le dossier system32 et essayé de charger l’une d’elles en Servlet constructeur System.loadLibrary
  • Dll requis copiées en tomcat_home/shared/lib et tomcat_home/common/lib
  • toutes ces dll sont en WEB-INF/lib de l'application web

166voto

Adam Batkin Points 20920

Pour System.loadLibrary() de travail, la bibliothèque (sur Windows, une DLL) doivent être dans un dossier quelque part sur votre PATH ou sur un chemin figurant dans l' java.library.path de la propriété du système (de sorte que vous pouvez lancer Java comme java -Djava.library.path=/path/to/dir).

De plus, en loadLibrary(), vous spécifiez le nom de base de la bibliothèque, sans l' .dll à la fin. Donc, pour /path/to/something.dll, il faudrait utiliser System.loadLibrary("something").

Vous avez aussi besoin de regarder l'exacte UnsatisfiedLinkError qui vous obtenez. Si elle dit quelque chose comme:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no foo in java.library.path

alors il ne peut pas trouver le foo (bibliothèque de foo.dll dans votre PATH ou java.library.path. Si elle dit quelque chose comme:

Exception in thread "main" java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()V

puis quelque chose de mal avec la bibliothèque elle-même dans le sens que Java n'est pas en mesure de mapper un natif de Java en fonction de votre application réelle natif de contrepartie.

Pour commencer, je voudrais mettre quelques traces autour de votre System.loadLibrary() appel pour voir si cela s'exécute correctement. Si elle déclenche une exception ou n'est pas dans un chemin de code qui est exécuté, puis vous obtiendrez toujours le dernier type d' UnsatisfiedLinkError expliqué ci-dessus.

Au passage, la plupart des gens mettent leur loadLibrary() des appels dans un initialiseur statique bloc dans la classe avec le natif de méthodes, pour s'assurer qu'il est toujours exécuté exactement une fois:

class Foo {

    static {
        System.loadLibrary('foo');
    }

    public Foo() {
    }

}

18voto

Alexandre Points 21

Changer la variable 'java.library.path' au moment de l'exécution n'est pas suffisant car il est lu une seule fois par la machine virtuelle Java. Vous devez le réinitialiser comme ceci:

 System.setProperty("java.library.path", path);
//set sys_paths to null
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
 

S'il vous plaît, prenez un butin sur: Changer le chemin de la bibliothèque Java à l'exécution .

11voto

Matt M Points 146

La réponse originale à cette question par Adam Batkin vous mènera à une solution, mais si vous redéployer votre webapp (sans redémarrage de votre conteneur web), vous devez exécuter dans l'erreur suivante:

java.lang.UnsatisfiedLinkError: Native Library "foo" already loaded in another classloader
   at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1715)
   at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1646)
   at java.lang.Runtime.load0(Runtime.java:787)
   at java.lang.System.load(System.java:1022)

Cela se produit parce que le chargeur de classe qui, à l'origine chargé de votre DLL toujours les références de cette DLL. Cependant, votre webapp est maintenant en cours d'exécution avec un nouveau chargeur de classe, et parce que la même JVM est en cours d'exécution et une JVM ne permet pas de 2 références à la même DLL, vous ne pouvez pas recharger . Ainsi, votre application ne peut pas accéder à la DLL existante et ne peut pas ouvrir un nouveau. Donc.... vous êtes coincé.

Tomcat, chargeur de classe de la documentation explique pourquoi votre reloaded webapp s'exécute dans un nouveau isolé du chargeur de classe et comment vous pouvez contourner cette limitation (à un niveau très élevé).

La solution est d'étendre Adam Batkin la solution un peu:

   package awesome;

   public class Foo {

        static {
            System.loadLibrary('foo');
        }

        // required to work with JDK 6 and JDK 7
        public static void main(String[] args) {
        }

    }

Placer un récipient contenant de JUSTE dans cette classe compilée dans le TOMCAT_HOME/lib dossier.

Maintenant, au sein de votre application web, vous avez juste à force de Tomcat pour faire référence à cette classe, ce qui peut être fait simplement comme ceci:

  Class.forName("awesome.Foo");

Maintenant, votre fichier DLL doit être chargé dans la commune de chargeur de classe, et peut être référencé à partir de votre webapp, même après avoir été redéployés.

Un sens?

Un travail exemplaire de référence peut être trouvé sur google code, statique-dll-programme d'amorçage .

8voto

Philip Whitehouse Points 2242

Vous pouvez utiliser System.load() pour fournir un chemin d'accès absolu qui est ce que vous voulez, plutôt que d'un fichier dans la bibliothèque standard de dossier pour les différents systèmes d'exploitation.

Si vous voulez des applications natives qui existent déjà, de les utiliser System.loadLibrary(String filename). Si vous voulez fournir votre propre, vous êtes probablement mieux avec load().

Vous devez également être en mesure d'utiliser loadLibrary avec l' java.library.path ensemble correctement. Voir ClassLoader.java pour la mise en œuvre de la source montrant à la fois les chemins d'accès en cours de vérification (OpenJDK)

4voto

Pour ceux qui recherchent java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path

Je faisais face à la même exception; J'ai tout essayé et les choses importantes pour que ça marche sont:

  1. Version correcte de pdf lib.jar (dans mon cas, il s'agissait d'une mauvaise version conservée dans le serveur d'exécution)
  2. Créez un dossier, conservez le fichier jar pdflib et ajoutez-le dans votre variable PATH.

Cela a fonctionné avec tomcat 6.

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