Aunque la potencia de la API de Java es más que suficiente para casi todo tipo de aplicaciones, algunas de ellas necesitan utilizar la potencia específica de una plataforma en concreto, por ejemplo para conseguir un poco más de velocidad y eficiencia.
Java permite incorporar en sus programas fragmentos de código nativo es decir, código compilado para una determinada plataforma, generalmente escrito en C/C++. Así se puede utilizar código específico de una plataforma, bibliotecas ya escritas...
Para ello Java cuenta con el JNI (Java Native Invocation). Hay que tener en cuenta que una aplicación que utilice este tipo de métodos estará violando las directrices de seguridad de la máquina virtual Java, motivo por el que no se permite incluir métodos nativos en applets de Java.
Para agregar métodos nativos Java a una clase de Java han de seguirse los siguiente pasos:
1. Escritura del programa Java, invocando métodos nativos como native.
2. Compilación del programa Java.
3. Creación de un archivo de cabecera nativo (.h)
4. Escritura de los métodos nativos.
5. Creación de una biblioteca con esos métodos nativos.
6. Ejecución del programa Java.
B. Ejemplo de uso de métodos nativosPara mostrar cómo utilizar los métodos nativos, vamos a crear un pequeño programa, escrito con métodos nativos, que lo único que hace es imprimir "¡Hola Mundo!!!". Para ello vamos a utilizar el JDK y un compilador de C.
Se advierte al lector que no se deje engañar por la simpleza del ejemplo que se va a desarrollar, porque la potencia del JNI va mucho más allá de lo que estas líneas dejan entrever. Para más información consulte [Morgan, 1999].
a.) Escritura del programa JavaEscribimos el programa Java en un fichero denominado HolaNativo.java.
El código Java que vamos a utilizar será:
public class HolaNativo{ public native void diHola(); static { System.loadLibrary("LibHola"); } public static void main( String[] args ) { new HolaNativo().diHola(); } }
El método nativo diHola() no tiene cuerpo porque será añadido mediante una biblioteca nativa denominada LibHola. Dicha biblioteca nativa es cargada mediante la sentencia loadLibrary(), sentencia que ha sido incluida como static para que sea ejecutada cada vez que se cree una instancia (objeto) de esta clase.
El programa principal tan sólo instancia un objeto de esta clase y utiliza el método nativo que imprime la cadena de "¡Hola Mundo!!!".
b.) Compilación del programa JavaAhora ya es posible compilar la clase Java HolaNativo que fue creada mediante la sentencia (utilizando el JDK):
javac HolaNativo.java c.) Creación de un fichero de cabecera nativo (.h)Un fichero de cabecera nativo es un fichero que habitualmente tiene la extensión ".h". En un fichero de este tipo se definen en C/C++ las interfaces públicas (clases, métodos o funciones, variables globales, constantes...).
La herramienta javah incluida en el JDK es capaz de crear automáticamente un fichero de cabecera para métodos nativos Java, con sólo invocarla indicando el nombre de la clase de la que extraer las cabeceras nativas:
javah HolaNativoEsta operación crea un fichero HolaNativo.h que será útil para crear los métodos nativos. Hay dos líneas importantes dentro de este fichero:
#include <jni.h> JNIEXPORT void JNICALL Java_HolaNativo_diHola(JNIEnv*,jobject);La primera línea importa una biblioteca JNI que valdrá a C/C++ para saber cómo crear los métodos nativos.
La segunda línea corresponde al método nativo que definimos.
Los métodos nativos suelen denominarse siempre como Java_Paquete_Clase_Metodo() aunque en este caso al no haber paquete esta parte se ha omitido.
Así mismo los métodos nativos reciben como parámetros JNIEnv* y jobject que permitirán al método nativo comunicarse con su entorno.
d.) Escritura de los métodos nativosSe ha de crear un fichero fuente nativo, en el que se defina el cuerpo de la función que actuará como método nativo. Este fichero lo denominaremos HolaNativo.c:
#include <jni.h> #include "HolaNativo.h" #include <stdio.h> JNIEXPORT void JNICALL Java_HolaNativo_DiHola( JNIEnv* e, jobject o ){ printf("¡Hola Mundo!!!\n"); }
En este programa se incluyen tres bibliotecas: La de JNI (jni.h), el fichero de cabecera ya creado (HolaNativo.h) y una biblioteca de C para imprimir (stdio.h).
Ser puede observar que el cuerpo del método nativo lo que hace es invocar a la función de C printf() que imprimirá por pantalla la cadena "¡Hola Mundo!!!".
e.) Creación de una biblioteca con esos métodos nativosCada compilador de C o C++ tiene su propia herramienta para crear bibliotecas compartidas (DLL en Windows o SO en UNIX).
Para crear la biblioteca se ha de compilar el fichero fuente nativo, y luego crear la biblioteca compartida mediante el programa correspondiente a su compilador.
Para esto cada compilador tiene su propia sintaxis, con lo que se tendrá que consultar la documentación del compilador en lo referente a la creación de bibliotecas. En cualquier caso algunos ejemplos de compilación en bibliotecas son:
Para el GCC de Solaris:
cc -G HolaNativo.c -o libHola.soPara Microsoft Visual C++ para Windows:
cl -LD HolaNativo.c -Fe libHola.dllEn cualquier caso asegúrese que la biblioteca creada tiene el mismo nombre con que se la invoca desde el archivo de clase Java en el método loadLibrary().
f.) Ejecución del programa JavaPara ejecutar este programa, debe invocarse:
java HolaNativoCon lo que se muestra por pantalla:
Hola MundoSe puede observar que la forma de creación, compilación y ejecución de la clase Java es igual que la utilizada para crear una aplicación Java normal, solo que al incluir métodos nativos, han de crearse bibliotecas y ficheros de cabecera antes de ejecutar el programa.