43 Code natif (JNI)
Dans ce chapitre, nous allons voir comment on peut mélanger du code écrit dans un autre langage à l'intérieur du code Java .
Précisons tout de suite que cette possibilité ne doit être utilisé que dans des cas exceptionnels. En effet, le fait
d'introduire du code natif dans Java enlève un certain nombre d'attraits de ce langage: la portabilité, l'indépenance de la
plate forme utilisé, possibilité de téléchargement etc...
Pourquoi donc vouloir mélanger Java avec un autre langage ?
Tout d'abord, Java ne permet d'accéder aux fonctionnalités spécifique d'un système. Par exemple, il n'est pas possible avec Java
de manipuler des cartes d'acquisition. Toutes ces manipulations proches du système se fera donc dans un autre langage et sera
interfacer avec Java pour le reste de l'application.
Ensuite, il peut être intéressant d'interfacer un code récent Java avec une application existante écrite dans un autre langage. La
récriture complète serait bien trop fastidieuse.
Enfin, il existe des application dans lesquelles des bouts critiques doivent s'exécuter de manière extrèmement efficace. On pourra
alors récrire ces parties cruciales dans un langage plus efficace (plus proche de la machine).
L'interface Java permettant de lier du code natif au code Java est désigné par le terme JNT (Java Native Interface) Dans ce qui
va suivre nous allons plus particulièrement nous intéresser à la programmation des méthodes natives en C et la fin du chapitre
présentera les particularité de ce type de lien avec C++.
Dans la communication entre Java et un autre langage comme C qui n'est pas un langage orienté objet, il y a plusieurs problèmes
à résoudre:
Mise en correspondance des identificateurs Java (Unicode ) en identificateurs C ou C++ .
Mise en correspondance des méthodes: C ne dispose ni d'objets ni de packages, il faut trouver, malgré tout un moyen
de faire correpondre une méthode Java (qui est sous la forme package.classe.méthode) à une fonction C .
Les méthodes (non statiques) s'applique sur des objets (implicitement this)
Lier l'invocation d'une méthode à l'exécution d'une fonction, par exemple
transmettre les paramètres entre la méthode Java et la focntion C
Manipulation des champs des classes
Gestion des erreurs avec des exceptions; C ne dispose d'un système d'exception.
Fiabilité du code: par exemple, les problèmes de gestion mémoire, de sécurité d'accès aux élements d'un tableaux, etc.
Création d'objets Java depuis C.
etc.
Un exemple
43.1.1 Déclarer une méthode native
Une méthode native est une méthode dont l'implantation est réalisée dans un autre langage que Java généralement du C ou C++.
Une méthode est qualifiée de native, lorsque il comporte le qualifier (ou modifier ) natif.
public native void afficherHello();
Il n'est évidemment pas question de donner une quelconque implantation de cette méthode puisqu'elle censé être faite dans un
autre langage que Java .
43.1.2 Charger la librarie C
Après implantation du code natif C, on devra la copiler et produire une bibliothèque dynamique. Cette bibliothèque devra être
chargée au chargement de la classe Hello. Le chargement d'une bibliothèque se fait avec la méthode
System.load(...) ou System.loadLibrary(...). En supposons que cette bibliothèque se nomme
libhello.so (pour UNIX ) ou libhello.dll (pour Windows ), voici le code complet de la classe Hello.
public class Hello
public native void afficherHello();
static System.load("Hello");
43.1.3 Créer le fichier .h
Avant d'implanter la fonction C qui sera mis en correspondance avec la méthode afficherHello, il faut
compiler le fichier Hello.java
créer la glue qui va permettre de lier le code C et le code Java .
La glue est constituée d'un fichier .h qui sera automatiquement produit par la commande javah.
% javac Hello
% javah -jni Hello
Cette commande produit le fichier Hello.h
#include
/* Header for class Hello */
#ifndef _Included_Hello
#define _Included_Hello
#pragma pack(4)
typedef struct ClassHello
char PAD; /* ANSI C requires structures to have a least one member
*/
ClassHello;
HandleTo(Hello);
#pragma pack()
#ifdef __cplusplus
extern "C"
#endif
extern void Hello_afficherHello(struct HHello *);
#ifdef __cplusplus
#endif
#endif
vous aurez noté que ce fichier convient également pour interfacer Java avec C++ .
43.1.4 Implanter la méthode native
Ce fichier va servir de glue en Java et C . A présent, on va pouvoir implanter la méthode native; il faudra respecter un certain
nombre de conventions dans cette implantation:
Inclure le fichier jni.h fourni avec la distribution de jdk ainsi le fichier Hello.h précédemment produit.
Chacune des méthodes à implanter devra être de la forme
JNIEXPORT type JNICALL Java_NomDePackage _NomDeClasse
_NomDeLaMethode (JNIEnv *env, jobject obj, ...)
Lorsque la classe appartient au package sans, comme dans notre exemple, le nom du package et le caractère _ le précédant sont
omis. Pour cet exemple, le prototype de fonction C sera donc de la forme
JNIEXPORT void JNICALL Java_Hello _afficherHello (JNIEnv *env, jobject
obj)
On remarquera que toutes ces méthodes admenttent au moins deux arguments: JNIEnv *env et jobject obj.
La variable env est un pointeur vers l'environnment Java et c'est cette dernière qui permet de récupérer les arguments de la
méthode et tout autre information provenant de l'environnement Java .
La variable obj est une référence vers l'objet sur lequel la méthode s'applique. Lorsqu'il s'agit d'une méthode static, la valeur de
cette référence est nulle.
#include <jni.h>
#include "Hello.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_Hello_afficherHello(JNIEnv *env, jclass obj)
{
printf("Coucou !!!\n");
}
43.1.5 Créer la bibliothèque dynamique
Il faut à présent compiler le fichier C et produire une bibliothèque dynamique
gcc -shared -I/usr/include/jdk-1.1.5/ -I/usr/include/jdk-1.1.5/genunix/
HelloImpl.c -o libHello.so
Cette commande est évidemment dépendante du système et de la configuration du système utilisée.
43.1.6 La touche final
A présent, tous les ingrédients sont là; il ne nous reste plus qu'à programmer un exemple d'utilisation.
public class Test
public static void main(String args[]) {
Hello h = new Hello();
h.afficherHello();
}
}
Une fois compilé cette classe, il ne reste plus qu' exécuter:
Hello !!!
43.2 Conversion des caractères unicode
Les caractères Unicode compris entre \u0000 et \u007f (caractères ASCII ) ne sont pas modifiés. Quant aux caractères
Unicode qui ne sont pas dans cette plage, le caractère \udddd est transformer en la suite de caractères _0dddd.
43.3 Conversion des données
43.3.1 Passage de paramètres
Pour implanter correctement les méthodes, il faut établir un moyen de convertir les données Java en données et inversement. A
chaque classe Java correspond une structure (struct) C et chaque membre de la classe garde le même qu'en Java , à la
conversion des caractères Unicode près.
43.3.2 Types primitifs
A chaque type primitif, il existe un type C :
Type Java
Type C
boolean
jboolean
byte
jbyte
char
jchar
short
jshort
int
jint
long
jlong
float
jfloat
double
jdouble
Lorsq'un type primitif est passé en argument d'une méthode native, ce passage sa fait par valeur.
Param.java
class Param {
public static native int somme(int x, int y);
static {
System.loadLibrary("Param");
}
}
ParamEx.java
class ParamEx {
public static void main(String[] args) {
System.out.println(Param.somme(3, 5));
}
}
ParamImpl.java
#include <jni.h>
#include "Param.h"
#include <stdio.h>
JNIEXPORT jint JNICALL Java_Param_somme(JNIEnv *env, jobject obj, jint X,
jint Y) {
return X + Y;
}
43.3.3 Les objets
Les objets Java ou les tableaux sont désigné en C par un jobject. Lorsq'une instance d'une classe est passée en argument
d'une méthode native, ce passage sa fait par référence.
Java met également à notre disposition les types plus fin pour minimiser les erreurs de programmation.
jobject
tous les objets.
jclass
Les instances de classes.
jstring
Les chaines
jarray
Les tableaux.
jobjectArray
Tableaux d'objets.
jbooleanArray
Tableaux de boolean.
jbyteArray
Tableaux de byte
jcharArray
Tableaux de char
jshortArray
Tableaux de short
jintArray
Tableaux de int
jlongArray
Tableaux de long
jfloatArray
Tableaux de float
jdoubleArray
Tableaux de double
jthrowable
Les exceptions
1 / 17 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans l'interface ou les textes ? Ou savez-vous comment améliorer l'interface utilisateur de StudyLib ? N'hésitez pas à envoyer vos suggestions. C'est très important pour nous!