0% ont trouvé ce document utile (0 vote)
7 vues45 pages

Cours sur Java Native Interface (JNI)

Ce document présente un cours sur l'interface Java Native Interface (JNI) dispensé par Jean-Michel Douin au Cnam Paris. Il couvre les interactions entre Java et C/C++, y compris la création d'objets, l'invocation de méthodes, et la gestion des exceptions. Des exemples de code et des outils utilisés sont également fournis pour illustrer les concepts abordés.

Transféré par

aMOR BENGOURICH
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
7 vues45 pages

Cours sur Java Native Interface (JNI)

Ce document présente un cours sur l'interface Java Native Interface (JNI) dispensé par Jean-Michel Douin au Cnam Paris. Il couvre les interactions entre Java et C/C++, y compris la création d'objets, l'invocation de méthodes, et la gestion des exceptions. Des exemples de code et des outils utilisés sont également fournis pour illustrer les concepts abordés.

Transféré par

aMOR BENGOURICH
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Cours Java Native Interface

Cnam Paris
jean-michel Douin,
version de Mars 2009

Notes de cours jni : de Java vers C/C++ et de C/C++ vers Java

Outils utilisés : JDK1.5, Visual C++ 6.0 (utilisé en ligne de commandes) et BlueJ2.2.1

1
JNI
Sommaire

• De Java vers C/C++

• De C/C++ vers Java


– lecture/écriture de données d'instance et de classes
– invocation de méthodes d'instance et de classes
– création d'objet
– création de tableaux et de String
– Levée et filtrage d'exceptions
– utilisation des moniteurs (de hoare)
– Entrées/sorties Série
– création de machine(s) Java

API JNI et une analogie avec l’Architecture de la


machine virtuelle

2
JNI
Bibliographie utilisée

Le tutorial JNI de Beth Stearns


• [Link]
• surtout : [Link]
• jni specification : [Link]

Un outil bien utile distribué par Sun


• [Link]
• [Link]

Un « essentiel » ouvrage sur le sujet


• Essential JNI: Java Native Interface, rob Gordon, Prentice hall.1998
ISBN 0-13-679895-0
• le site de l ’éditeur [Link]

les instructions et l ’architecture de la machine virtuelle Java reflètent les


fonctionnalités de l’ API JNI
• The VM [Link]://[Link]/docs/books/vmspec/html

3
JNI
JNI Pourquoi ?

• Applications existantes dans un environnement Java, avec ou sans les


sources

• Programmation d ’un périphérique, logiciel de base, Entrées/Sorties,


Cartes d ’acquisition, de commandes
– (Adressage physique, Accès au matériel, aux pilotes de la carte,
interruptions…

• Développement en C/C++, tout en bénéficiant de l ’environnement Java


IHM en Java, application en C, Applet, accès à l ’internet

• Code natif pour de meilleures performances en temps d ’exécution

• Portabilité ?

4
JNI
JNI Présentation

• Deux aspects
– de Java vers C/C++

– de C/C++ vers Java


– en venant de Java

– ou depuis une application ordinaire

• L ’API JNI offre l ’accès à la machine virtuelle


– accès aux variables d ’instance, appel de méthodes, chargement d ’une
classe, création d ’instances…
– Mécanisme de bas-niveau...
– Exceptions,
– Threads….

5
JNI
De Java vers C(jc)

• 1) usage du mot clé native

• 2) génération par les outils de SUN de l ’interface « .h » >javah -jni


Exemple

• 3) génération de la DLL (Win32,.dll), ou de la SOL(solaris,.so)

• 4) exécution

notes :
nécessite l ’accès à $JDK_HOME\include
(en fonction de la plate-forme $JDK_HOME\include\win32(ou solaris))
et l ’exécution sous DOS de C:\Program Files\Microsoft Visual Studio\VC98\Bin\[Link]
Setting environment for using Microsoft Visual C++ tools.

6
JNI
jc) 1) Le source Java

public class JavaVersC {


public native void bonjour(); // (1)

public static void main(String args[]) {


new JavaVersC().bonjour();
}

static{
[Link]("VersC"); // (2)
}
}

• >javac [Link]
• (1) emploi de native
• (2) chargement de la librairie (DLL/sol) dans laquelle sera implémentée le
code C de bonjour

7
JNI
jc) Le source C : interface

• 2) génération de l ’interface (.h) par javah


• >javah -jni JavaVersC

/* DO NOT EDIT THIS FILE - it is machine generated */


#include <jni.h>
/* Header for class JavaVersC */
#ifndef _Included_JavaVersC
#define _Included_JavaVersC
#ifdef __cplusplus
extern "C" {
#endif
/* Class: JavaVersC
* Method: bonjour
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JavaVersC_bonjour(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

8
JNI
jc) le source C : Implémentation

#include <stdio.h>
#include "JavaVersC.h"

JNIEXPORT void JNICALL Java_JavaVersC_bonjour (JNIEnv *env, jobject j){

printf("Java_JavaVersC_bonjour");
}

• 3) Génération de la DLL, ([Link])


– Avec visual c++
– cl -I%JDK_HOME%\include -I%JDK_HOME%\include\win32 -LD JavaVersC.c -
[Link]

• 4) Exécution par
– >java JavaVersC

9
JNI
jc) JNIENV et jobject

• JNIEnv *env
– Il s ’agit de l ’environnement de la machine Java associé au « Thread »
courant, (le Thread ayant engendré l ’appel de la méthode native
bonjour)

• jobject j
– Il s ’agit de l ’objet receveur du message bonjour(), ici l ’instance créée
dans la méthode main
– (jclass j, dans le cas d ’une méthode de classe )

• En résumé
– A chaque appel d ’une méthode native sont transmis par la machine
Java
• un environnement
• l ’objet receveur ou la classe si c'est une méthode classe
• et éventuellement les paramètres

10
JNI
De C vers Java(cj)

• depuis une DLL/SO engendrée par javah


– emploi du mot clé native

– java -----native----------->C/C++
– |
– java <----API_JNI--------- C/C++

• ou depuis une application C/C++ ordinaire

– java <----API_JNI--------- C/C++

11
JNI
cj) De C vers Java

• Primitives d ’accès à la machine Java env

j
Variables
d’instance

Source C class
<jni.h> Méthodes
Byte d ’instances
code méthodes
de classe
Variables de
classe

12
JNI
Fonctions de JNI

• Versions
• Opérations sur les classes
• Exceptions
• Références locales et globales
• Opérations sur les objets
• Accès aux champs des objets
• Appels de méthodes d'instances
• Accès aux champs statiques
• Appels de méthodes de classes
• Opérations sur les instances de type String
• Opérations sur les tableaux
• Accès aux moniteurs
• Interface de la JVM

13
JNI
cj) Accès aux Variables d'instance

• GetFieldID, Get<type>Field, Set<type>Field

• public class Exemple{ obj


– private int x;
x Variables
– public native void setX(int val); d’instance
– }

• En C :
• JNIEXPORT void JNICALL Java_Exemple_setX (JNIENV
*env, jobject obj, jint val){
– jclass classe = (*env)->GetObjectClass(env,obj);
– jfieldID fid = (*env)->GetFieldID(env,classe,"x","I");
– (*env)->SetIntField(env,obj,fid,val) ;
– }

– instructions JVM : getfield, putfield

14
JNI
[Link] au complet

public class Exemple{


private int x;
public native void setX(int val);

static{
[Link]("Exemple");
}

public static void main(String args[]) {


Exemple e = new Exemple();
[Link](33);
[Link](" dites " + e.x);
}
}

15
JNI
Exemple.c au complet

#include "Exemple.h"

JNIEXPORT void JNICALL Java_Exemple_setX(JNIEnv* env,


jobject obj, jint val){
jclass cl = (*env)->GetObjectClass(env,obj);
jfieldID fid = (*env)->GetFieldID(env,cl,"x","I");
(*env)->SetIntField(env,obj,fid,val) ;
}

16
JNI
Les commandes (win32) au complet

javac -classpath . [Link]


javah -jni -classpath . Exemple
cl /I%JDK_HOME%\include /I%JDK_HOME%\include\win32 /LD Exemple.c /[Link]
java -cp . Exemple

17
JNI
Retour sur JNIENV *env
env

GetFieldID

SetIntField

GetObjectClass

etc...

etc...
en C : (*env)->GetFieldID(env,...)
en C++ : env->GetFieldID(...)
18
JNI
JNIENV (un extrait)
typedef const struct JNINativeInterface_ *JNIEnv;
struct JNINativeInterface_ {
void *reserved0;

jclass (JNICALL *FindClass) (JNIEnv *env, const char *name);

void (JNICALL *SetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
jfieldID (JNICALL *GetFieldID)(JNIEnv *env, jclass clazz, const char *name, const
char *sig);

19
JNI
JNIENV *env

• Inspiré du JRI de Netscape

• Chaque fonction est accessible par un déplacement fixe


dans une table,
• Une table peut donc être substituée par une autre sans
avoir à recompiler,
• L'implantation des fonctions de cette table est à la charge
du fournisseur de la JVM,
• Le code C/C++ d'accès à la JVM devient portable

• Analogue à l'implémentation de la table des méthodes


virtuelles d'une instance

20
JNI
cj) Accès aux Variables de classes

• GetStaticFieldID, GetStatic<type>Field,
SetStatic<type>Field classe

x
• public class Exemple{
– private static int x;
Variables de
– public native void setStaticX(int val); classe
– }

• JNIEXPORT void JNICALL Java_Exemple_setStaticX


• (JNIENV *env, jobject obj, jint val){
– jclass classe = (*env)->GetObjectClass(env,obj);
– jfieldID fid = (*env)->GetStaticFieldID(env,classe,"x","I");
– (*env)->SetStaticIntField(env,classe,fid,val) ;
– }

– instructions JVM : getstatic, putstatic

21
JNI
cj) Appels de méthodes d ’instance

obj
• Call<type>Method

• public class Exemple{


– public void p(){[Link]( "appel de p ");}
– public native void callP(int val); table des
– } méthodes

• JNIEXPORT void JNICALL Java_Exemple_callP


(JNIENV *env, jobject obj){
– jclass classe = (*env)->GetObjectClass(env,obj);
– jmethodID mid = (*env)->GetMethodID(env,classe,"p","()V");
– (*env)->CallVoidMethod(env,obj,mid) ;
– }

– instruction JVM : invokevirtual

22
JNI
cj) Appels de méthodes de classe
classe
• CallStatic<type>Method

• public class Exemple{


– public static void p(){[Link]( "appel de p ");}
– public native void callP(int val); table des
– } méthodes de
classe

• JNIEXPORT void JNICALL Java_Exemple_callP


(JNIENV *env, jobject obj){
– jclass classe = (*env)->GetObjectClass(env,obj);
– jMethodID mid = (*env)->GetStaticMethodID(env,
classe,"p", "()V");
– (*env)->CallStaticVoidMethod(env, classe,mid) ;
– }

– instruction JVM : invokestatic

23
JNI
cj) Types natifs

• jni.h, interpreter.h,oobj.h,typecodes.h

• Types natifs / types java

– jbyte / byte, jshort / short, jint / int


– ….

– jobject / Object, jclass / Class, jstring / String, jarray / array,


– jthrowable / Throwable

– sur la palte-forme Win32


– nous avons typedef jijnt long;
– voir fichier %JDK_HOME%\include\win32\jni_md.h

24
JNI
Signature des méthodes
• FieldType ::= BaseType | ObjectType | ArrayType
• BaseType
• B byte
• C char
• D double
• F float
• I int
• J long
• S short
• Z boolean
• ObjectType
• L<classname>;
• ArrayType
• [ table
• MethodDescriptor ::= ( FieldType *) ReturnDescriptor
• ReturnDescriptor ::= FieldType | V
• V si le type retourné est void

25
JNI
Signature des méthodes en "clair"

• >javap -s -private JavaVersC

Compiled from [Link]


public synchronized class JavaVersC extends [Link]
/* ACC_SUPER bit set */
{
public native void bonjour();
/* ()V */
public static void main([Link][]);
/* ([Ljava/lang/String;)V */
public JavaVersC();
/* ()V */
static static {};
/* ()V */
}
26
JNI
Objets et classe

• NewObject, NewObjectA,NewObjectV
création d ’une instance
obtention de la classe
obtention du constructeur
passage des paramètres et création
...//en Java : ClasseA newObj = new ClasseA(10,"hello");

jclass classe = (*env)->FindClass("ClasseA");


jMethodID mid = (*env)->GetMethodID(classe,
"<init>",
"(ILjava/lang/String;)V");
jint val = 10;
jstring str = (*env)->NewStringUTF(env, "hello");
jobject newObj = (*env)->NewObject(env,
classe,mid,val,str) ;
}

• instruction JVM : new et invokespecial


27
JNI
instanceof

• IsInstanceOf

• class A{}
• class B extends A{void callP(boolean b){…};}

• ...// obj est de classe déclarée A mais constatée B

– jclass classeB = (*env)->FindClass("B");


– if ((*env)->IsInstanceOf(obj,classeB)){
– jMethodID mid = (*env)->GetMethodID(classeB,
– "callP",
– "(Z)V");
– jbool val = JNI_TRUE;
– (*env)->CallVoidMethod(obj,mid,val) ;
– }

– instruction JVM : instanceof, (checkcast)

28
JNI
Tableaux et String

• NewObjectArray,
• public class Exemple{
– public void p(){String sa = newArray(10);}
– public native String [] newArray(int taille);
– }
• ...
– jclass classe = (*env)->FindClass(env, "java/lang/String");
– jObjectArray newArr = (*env)->NewObjectArray(env, taille,classe,NULL);
– for(int i = 0; i< taille; i++){
– str = (*env)->NewStringUTF("hello");
– (*env)->SetObjectArrayElement(env, newArr,i,str);
– (*env)->DeleteLocalRef(env, str);
– }
– return newArr;
– }
– DeleteLocalRef -> str a 2 références, en jni et en java (gc)

– instruction JVM : newarray

29
JNI
Objets et ramasse miettes

• Chaque objet crée par JNI ne peut être collecté par le


ramasse miettes Java, (l'objet str est référencé dans la
machine Java)

– DeleteLocalRef(str) // de l'exemple précédent

– permet de libérér cet objet (autorise la récupération mémoire par le ramasse


miettes)

– NewGlobalRef(obj);
– "bloque" l'objet en mémoire

30
JNI
Levée d ’exceptions
• Throw ThrowNew,...

JNIEXPORT void JNICALL Java_JavaVersC_bonjour (JNIEnv *env){


jclass cl; jmethodID mid; jthrowable exc;

cl = (*env)->FindClass(env,"ExceptionVenantDeC");
mid = (*env)->GetMethodID(env,cl,"<init>","()V");
exc = (jthrowable)(*env)->NewObject(env,cl,mid);

(*env)->Throw(env,exc);

• instruction JVM : athrow

31
JNI
Côté Java

public class ExceptionVenantDeC extends Exception{


public ExceptionVenantDeC(String msg){
super(msg);
}
public ExceptionVenantDeC(){}
}

public native static void bonjour()throws ExceptionVenantDeC;


/* */
{
try{
...
}catch(ExceptionVenantDeC e){
[Link]();
}
}

32
JNI
Une variante : ThrowNew

JNIEXPORT void JNICALL Java_JavaVersC_bonjour (JNIEnv *env){


jclass cl; jmethodID mid; jthrowable exc;

cl = (*env)->FindClass(env,"ExceptionVenantDeC");
(*env)->ThrowNew(env,cl," appel de (*env)->ThrowNew/3 ");

33
JNI
Filtrage des Exceptions en C

• ExceptionClear, ExceptionOccurred, ExceptionDescribe,FatalError

– jthrowable exc;
– exc = (*env)->ExceptionOccurred(env);
– if(exc != NULL){
– // catch(Exception1 e){ …}
– if((*env)->IsInstanceof(env,exc,Exception1){
– ……… //
– (*env)->ExceptionClear();
– }
– }

– Avec
– jclass Exception1 = (*env)->FindClass(env, "Exception1");

34
JNI
Monitor

• MonitorEnter, MonitorExit
– // l'équivalent de l'instruction synchronized
– (*env)->MonitorEnter(env,obj);

– //du code C/C++

– (*env)->MonitorExit(env,obj);
– }
– instructions JVM : monitorenter, monitorexit

– Appels de wait et notify par les primitives GetMethodID et CallVoidMethod


– jclass classe = (*env)->GetObjectClass(env,obj);
– jMethodID waitMid = (*env)->GetMethodID(env,classe,"wait","()V");
– (*env)->CallVoidMethod(env,obj,waitMid);
– if((*env)->ExceptionOccured()!=NULL))
– // une exception est générée en Java, mauvais usage de Wait ...
– }

35
JNI
Deux exemples
• Entrées/Sorties Voie Série
• Accès au « Windows Registry »
• …

36
JNI
Entrées/Sorties Voie Série
• Win32Port Markus Bauer, (disponible sur [Link]

• public class Win32Port{

• public native boolean open(int pnr, String par, boolean handshake);


• public native void clear(int pnr);
• public native void setTimeout(int pnr, int tout);
• public native int getByte(int pnr);
• public native int getBytes(int pnr, byte[] bytes);
• public native boolean putByte(int pnr, int b);
• public native int putBytes(int pnr, byte[] bytes);
• public native boolean close(int pnr);

• static {
• [Link]("portcom");
• }}

37
JNI
Accès à la base de registres sous Windows
• [Link]
eyTest/

• Un lien à suivre … et à mettre en Œuvre …

38
JNI
Appel de la machine Java

• le source C ordinaire
– utilisation de [Link]
– chargement et appel de la machine Java depuis le point d'entrée main

• le source Java ordinaire


– n'importe quelle application

39
JNI
Le source C
#include <jni.h>

int main(int argc, char *argv[]){


// declarations ici
options[0].optionString = "-[Link]=.";
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.options = options;

res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);


res = JNI_CreateJavaVM(&jvm, &env, &vm_args);
classe = (*env)->FindClass(env, "CVersJava");
methodeID = (*env)->GetStaticMethodID(
env,classe,"main","([Ljava/lang/String;)V");

jstr = (*env)->NewStringUTF(env," depuis du c !!!");


args = (*env)->NewObjectArray(
env,1,(*env)->FindClass(env,"java/lang/String"),jstr);
(*env)->CallStaticVoidMethod(env,classe,methodeID,args);
(*jvm)->DestroyJavaVM(jvm);
} return (0);}
40
JNI
Le source Java

• public class CVersJava{



• public static void main(String [] args){
• [Link]("en java dans main " + args[0]);
• }
• }

41
JNI
Le source Complet (1)
#include <jni.h>
#include <stdlib.h>

int main(int argc, char *argv[]){


JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
JavaVMOption options[1];

jint res;
jclass classe;
jmethodID methodeID;
jstring jstr;
jobjectArray args;
char classpath[1024];

options[0].optionString = "-[Link]=.";
options[1].optionString = "-verbose:jni";
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 1;
vm_args.options = options;

42
JNI
Le source Complet (2)

res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);


if (res==JNI_ERR){
printf(" erreur lors de la création de la JVM ....\n");
return 1;
}
classe = (*env)->FindClass(env, "CVersJava");
methodeID = (*env)->GetStaticMethodID( env,classe,"main","([Ljava/lang/String;)V");

jstr = (*env)->NewStringUTF(env," depuis du c !!!");


args = (*env)->NewObjectArray(env,1,(*env)->FindClass(env,"java/lang/String"),jstr);
(*env)->CallStaticVoidMethod(env,classe,methodeID,args);
(*jvm)->DestroyJavaVM(jvm);

return (0);
}

cl -I%JDK_HOME%\include -I%JDK_HOME%include\win32 SimpleHttpd.c


%JDK_HOME%\lib\[Link]
set path = %JDK_HOME\jre\bin\client\;%path% accès à [Link]

43
JNI
Un serveur Web depuis C …

….
res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if (res==JNI_ERR){
printf(" erreur lors de la création de la JVM ....\n");
return 1;
}
classe = (*env)->FindClass(env, "SimpleHttpd2");
methodeID = (*env)->GetStaticMethodID( env,classe,"main","([Ljava/lang/String;)V");
args = (*env)->NewObjectArray(env,0,(*env)>FindClass(env,"java/lang/String"),NULL);

(*env)->CallStaticVoidMethod(env,classe,methodeID,args);

return (0);
}

44
JNI
Conclusion

45
JNI

Vous aimerez peut-être aussi