Les FAQs Java :
FAQ JAVA FAQ Java EE FAQ Java ME FAQ Java XML FAQ JavaFX FAQ Java GUI FAQ Struts FAQ JSF FAQ JDBC JDO FAQ Hibernate FAQ Spring FAQ Eclipse FAQ NetBeans FAQ JCreator FAQ Maven 2

FAQ JavaConsultez toutes les FAQ

Nombre d'auteurs : 53, nombre de questions : 231, dernière mise à jour : 26 janvier 2014 

 
OuvrirSommaireGénéralitésJNI

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.

Créé le 21 octobre 2007  par adiGuba

Lien : Java Native Interface - API & Developer Guides

La variable système java.library.path comporte une liste de répertoire qui seront utilisés par la machine virtuelle pour rechercher les librairies 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 librairies 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 :

 
Sélectionnez
String javaLibraryPath = System.getProperty("java.library.path");

Le nom exact des libraries dépends des conventions. Par exemple si on charge la librairie "hello" :

  • 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 vis System.setProperty(), ces modifications ne seront pas prise en compte lors du chargement des librairies, 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 reflection, 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 Sun :

 
Sélectionnez
/**
 * 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 Sun 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);
		}
	}
}

Encore une fois attention à ce code qui n'est pas portable !

Pour charger une librairie 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 librairie...

Mis à jour le 20 décembre 2009  par adiGuba

Lien : System.getProperty()
Lien : File.pathSeparatorChar

Les codes sources présentés sur cette page sont libres de droits, et vous pouvez les utiliser à votre convenance. Pour le reste, ce document constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Ce document issu de http://www.developpez.com est soumis à deux licences, en fonction des contributeurs : - Les contributions de Clément Cunin et Johann Heymes sont soumises aux termes de la la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies des contributions de Clément Cunin et Johann Heymes tant que cette note apparaît clairement : "Ce document issu de http://www.developpez.com est soumis à la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies de cette page tant que cette note apparaît clairement". - Pour ce qui est des autres contributions : Copyright © 2014 Developpez LLC : Tous droits réservés Developpez LLC. Aucune reproduction, ne peut en être faite sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.