Commencer avec jni

Premiers pas avec JNI

JNI signifie Java Native Interface. Il s’agit d’un mécanisme permettant d’appeler un code natif à partir d’une application Java exécutée sous le contrôle de la JVM et vice versa. Le code natif signifie le code compilé pour la plate-forme cible. Le code de code natif est généralement écrit en C ou C++, mais il peut être écrit dans n’importe quel langage disposant d’un compilateur pour la plate-forme cible.

JNI est utile lorsque

  • Une application Java doit accéder à des ressources spécifiques à une plate-forme et il n’existe pas de bibliothèque Java avec les fonctionnalités requises. La ressource peut être un matériel spécifique, des capteurs ou autre.
  • Une application Java doit effectuer une tâche critique en termes de performances et le code natif peut être plus rapide ou avec moins d’empreinte que le bytecode Java. Néanmoins, soyez trop sûr de vous JVM est capable de faire beaucoup d’optimisation et une implémentation naïve en C/C++ sera probablement plus lente.
  • Une application en C/C++ (ou autre langage) veut utiliser une fonctionnalité fournie dans une librairie java.

Pour commencer avec JNI, vous avez besoin

  • JDK ou quelque chose qui est capable de compiler Java en bytecode.
  • Compilateur pour compiler le code natif.

L’exemple hello world suivant est une application Java simple qui appelle une fonction C. L’exemple peut être compilé par javac à partir du compilateur JDK et gcc C.

Code Java :

public class JNIExample {

    public static void main(String[] args) {
       // The loadLibrary search for the native library (libnative.so in this case)
       System.loadLibrary("native");
       String s = "Hello JNI";
       JNIExample example = new JNIExample();
       example.doPrint(s);
   }

   // The method with native code (written in C) must be declared with native prefix
   public native void doPrint(String message);

}

Code C :

#include <jni.h>
#include <stdio.h>

/* the function that is called from java must be declered with decorators
 * JNIEXPORT and JNICALL.
 * The function name is constructed as Java_ClassName_MethodName
 * Function parameters correspond parameters in java but there are 2 extra parameters
 * JNIEnv is a pointer to java envoronmet and jobject is a reference to caller object.
 * Caller object is the instance of the JNIExample in this case.
 */
JNIEXPORT void JNICALL Java_JNIExample_doPrint(JNIEnv *e, jobject obj, jstring message) {
    const char *c_message;
    /* It is necessary to convert java objects like string to something C native */
    c_message = (*e)->GetStringUTFChars(e, message, NULL);
    printf("%s\n", c_message);
    /* in the end it is necessary to free resources allocated by Get above */
    (*e)->ReleaseStringUTFChars(e, message, c_message);
}