Comenzando con jni

Primeros pasos con JNI

JNI significa interfaz nativa de Java. Es un mecanismo de cómo llamar a un código nativo desde una aplicación Java que se ejecuta bajo el control de JVM y viceversa. Código nativo significa código compilado para la plataforma de destino. El código de código nativo normalmente se escribe en C o C++, pero se puede escribir en cualquier lenguaje que tenga un compilador para la plataforma de destino.

JNI es útil cuando

  • Una aplicación Java necesita acceder a los recursos específicos de una plataforma y no hay una biblioteca Java con la funcionalidad requerida. El recurso puede ser un hardware específico, sensores o lo que sea.
  • Una aplicación de Java tiene que realizar una tarea crítica de rendimiento y el código nativo puede ser más rápido o ocupar menos espacio que el código de bytes de Java. Sin embargo, sea demasiado seguro de sí mismo. JVM es capaz de optimizar mucho y una implementación ingenua en C/C++ probablemente será más lenta.
  • Una aplicación en C/C++ (u otro idioma) quiere usar una función provista en una biblioteca Java.

Para empezar con JNI necesitas

  • JDK o algo que pueda compilar Java a bytecode.
  • Compilador para compilar el código nativo.

El siguiente ejemplo de hola mundo es una aplicación Java simple que llama a una función C. El ejemplo puede ser compilado por javac desde JDK y el compilador gcc C.

Código 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);

}

Código 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);
}