FAQ Java et le natif Consultez toutes les FAQ
Nombre d'auteurs : 11, nombre de questions : 31, dernière mise à jour : 28 février 2016 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur le forum Java de http://java.developpez.com ainsi que l'expérience personnelle des auteurs.
Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.
Sur ce, nous vous souhaitons une bonne lecture.
Java Native Interface (JNI) est une interface de programmation standard permettant d'appeler des fonctions natives au sein d'une classe Java.
Pour cela, la méthode Java est marqué avec le mot-clef native, et l'outil javah (fournit avec le JDK) permet de générer un fichier d'entête C contenant la signature de la fonction native à implémenter et à exporter dans une librairie dynamique.
Le code natif n'étant pas binairement portable, il est nécessaire de générer une librairie par système/architecture cible.
JNI est souvent utilisé pour pallier les limites de Java dès que l'on s'approche des fonctionnalités systèmes spécifiques à un système.
La variable système java.library.path comporte une liste de répertoire qui seront utilisés par la machine virtuelle pour rechercher les bibliothèques natives via la méthode System.loadLibrary() (*.dll pour Windows, *.so pour Unix/Linux, *.jnilib pour Mac).
Par défaut, Java respecte les conventions du système hôte pour le chargement des bibliothèques natives. Cela implique deux points.
La valeur par défaut du java.library.path dépend de variable d'environnement système et utilise son séparateur de chemin ( ';' sous Windows et ':' pour les autres systèmes - on peut utiliser la valeur de File.pathSeparatorChar pour obtenir cette information dynamiquement) :
- Sous Windows, cela correspond à la variable d'environnement PATH (également utilisé pour rechercher les applications).
- Sous Unix/Linux, cela correspond à la variable d'environnement LD_LIBRARY_PATH.
- Sous Mac, cela correspond à la variable d'environnement DYLD_LIBRARY_PATH.
En Java on peut utiliser la méthode System.getProperty() pour vérifier sa valeur :
Code java : | Sélectionner tout |
String javaLibraryPath = System.getProperty("java.library.path");
- Sous Windows, cela recherchera un fichier nommé hello.dll.
- Sous Unix/Linux, cela recherchera un fichier nommé libhello.so.
- Sous Mac, cela recherchera un fichier nommé libhello.jnilib.
Il est possible de modifier la valeur du java.library.path en redéfinissant la valeur de la propriété lors du lancement de l'application, en rajoutant le paramètre -Djava.library.path=la_nouvelle_valeur lors de l'appel de la JVM.
Toutefois, bien qu'il soit possible de modifier la valeur de la propriété java.library.path pendant l'exécution de l'application via System.setProperty(), ces modifications ne seront pas prise en compte lors du chargement des bibliothèques, car la valeur de la propriété n'est pas réévaluer.
Actuellement la seule solution pour forcer la valeur à être réévalué est d'utiliser de la réflectivité, ce qui rend le code non-standard et non-portable. Cela peut toutefois s'avérer utile dans certain cas. Voici le code spécifique à la JVM de Oracle :
Code java : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | /** * Ajoute un nouveau répertoire dans le java.library.path. * @param dir Le nouveau répertoire à ajouter. */ public static void addToJavaLibraryPath(File dir) { final String LIBRARY_PATH = "java.library.path"; if (!dir.isDirectory()) { throw new IllegalArgumentException(dir + " is not a directory."); } String javaLibraryPath = System.getProperty(LIBRARY_PATH); System.setProperty(LIBRARY_PATH, javaLibraryPath + File.pathSeparatorChar + dir.getAbsolutePath()); resetJavaLibraryPath(); } /** * Supprime le cache du "java.library.path". * Cela forcera le classloader à revérifier sa valeur lors du prochaine chargement de librairie. * * Attention : ceci est spécifique à la JVM de Oracle et pourrait ne pas fonctionner * sur une autre JVM... */ public static void resetJavaLibraryPath() { synchronized(Runtime.getRuntime()) { try { Field field = ClassLoader.class.getDeclaredField("usr_paths"); field.setAccessible(true); field.set(null, null); field = ClassLoader.class.getDeclaredField("sys_paths"); field.setAccessible(true); field.set(null, null); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } |
Pour charger une bibliothèque en dehors du library.path standard, la meilleure solution reste l'utilisation de la méthode System.load(String) en lui passant le chemin complet vers la bibliothèque ...
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.