Il est possible de créer un fichier JAR unique avec toutes les dépendances, y compris les bibliothèques JNI natives pour une ou plusieurs plates-formes. Le mécanisme de base consiste à utiliser System.load (File) pour charger la bibliothèque au lieu de System.loadLibrary (String) typique qui recherche la propriété système java.library.path. Cette méthode rend l'installation beaucoup plus simple car l'utilisateur n'a pas à installer la bibliothèque JNI sur son système, au détriment, cependant, que toutes les plates-formes peuvent ne pas être prises en charge car la bibliothèque spécifique pour une plate-forme peut ne pas être incluse dans le fichier JAR unique .
Le processus est le suivant:
- inclure les bibliothèques JNI natives dans le fichier JAR à un emplacement spécifique à la plate-forme, par exemple à NATIVE / $ {os.arch} / $ {os.name} /libname.lib
- créer du code dans un initialiseur statique de la classe principale pour
- calcule os.arch et os.name actuels
- recherchez la bibliothèque dans le fichier JAR à l'emplacement prédéfini à l'aide de Class.getResource (String)
- s'il existe, extrayez-le dans un fichier temporaire et chargez-le avec System.load (File).
J'ai ajouté une fonctionnalité pour faire cela pour jzmq, les liaisons Java de ZeroMQ (plug sans vergogne). Le code peut être trouvé ici . Le code jzmq utilise une solution hybride afin que si une bibliothèque intégrée ne peut pas être chargée, le code reviendra à la recherche de la bibliothèque JNI le long du chemin java.library.path.
UnsatisfiedLinkError
comme chargement de la première dll veut implicitement charger la dernière, mais je ne peux pas la trouver car elle est cachée dans le fichier jar. Le chargement de la dernière DLL en premier n'aide pas non plus.DLL
doivent être connus à l'avance et leur emplacement doit être ajouté dans laPATH
variable d'environnement.https://www.adamheinrich.com/blog/2012/12/how-to-load-native-jni-library-from-jar/
est un excellent article, qui résout mon problème.
Dans mon cas, j'ai le code suivant pour initialiser la bibliothèque:
la source
Jetez un œil à One-JAR . Il encapsulera votre application dans un seul fichier jar avec un chargeur de classe spécialisé qui gère entre autres les "jars dans les jars".
Il gère les bibliothèques natives (JNI) en les décompressant dans un dossier de travail temporaire selon les besoins.
(Avertissement: je n'ai jamais utilisé One-JAR, je n'en ai pas encore eu besoin, je l'ai juste mis en signet pour un jour de pluie.)
la source
1) Incluez la bibliothèque native dans votre JAR en tant que ressource. Par exemple. avec Maven ou Gradle et la mise en page standard du projet, placez la bibliothèque native dans le
main/resources
répertoire.2) Quelque part dans les initialiseurs statiques de classes Java, liés à cette bibliothèque, mettez le code comme suit:
la source
JarClassLoader est un chargeur de classe pour charger des classes, des bibliothèques natives et des ressources à partir d'un seul JAR monstre et à partir de JAR à l'intérieur du JAR monstre.
la source
Vous devrez probablement dissocier la bibliothèque native du système de fichiers local. Autant que je sache, le morceau de code qui effectue le chargement natif regarde le système de fichiers.
Ce code devrait vous aider à démarrer (je ne l'ai pas regardé depuis un moment, et c'est dans un but différent, mais devrait faire l'affaire, et je suis assez occupé pour le moment, mais si vous avez des questions, laissez un commentaire et je répondrai dès que possible).
la source