Java Native Interface - JNI

Java Schnittstelle zu plattform-spezifischen Funktionsaufrufen.

Kurzanleitung

Java Klasse erzeugen

In einer Jave-Klasse eine Methode als native deklarieren.

public class HalloWelt {

    public native void hallo();

    static {
       System.loadLibrary("HalloWelt"); 
    }

    public static void main(String args[]) {
       HalloWelt welt = new HalloWelt();
       welt.hallo();
    }

}

Die externe Bibliothek wird statisch mit

static {
    System.loadLibrary("HalloWelt"); 
}

eingebunden.

Header Datei erzeugen

Java Klasse compilieren:

javac HalloWelt.java

Header Datei aus der compilierten Klasse erzeugen:

javah -jni HalloWelt

javah erzeugt eine Datei HalloWelt.h mit folgendem Inhalt:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HalloWelt */

#ifndef _Included_HalloWelt
#define _Included_HalloWelt
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HalloWelt
 * Method:    hallo
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HalloWelt_hallo
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Funktionen implementieren

Deklarierte Funktionen in der erzeugten Header Datei in HalloWelt.c implementieren:

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

JNIEXPORT void JNICALL Java_HalloWelt_hallo (JNIEnv * env, jobject object) {
    printf("Hallo, Hallo!\n");
}

Bibliothek erstellen

Es muss der korrekte Pfad zu den Include Verzeichnissen gesetzt sein, wo sich jni.h befindet. Mit gesetzter Umgebungsvariable $JAVA_HOME compilieren:

gcc -fPIC -c HalloWelt.c -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux

Direkt:

gcc -fPIC -c HalloWelt.c -I/usr/lib/jvm/default/include -I/usr/lib/jvm/default/include/linux

Mac OSX:

gcc -fPIC -c HalloWelt.c -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers

Linken:

ld -shared -soname libHalloWelt.so.l -o libHalloWelt.so HalloWelt.o

Der Linux-Dateiname muss stets lib[NAME] lauten, die Bibliothek wird später in Java unter NAME dann eingebunden. Greift der C Code auf fremde Bibliotheken mit zu, können diese mit ld mit eingebunden werden

ld -shared -soname libHalloWelt.so.l -o libHalloWelt.so HalloWelt.o XY.o XYZ.o ZZZ.o

Der Pfad zur neu erstellen Bibliothek muss der JVM mitgeteilt werden. Entweder direkt als Parameter java.library.path im Aufruf:

java -Djava.library.path=./ HalloWelt

oder die Bibliothek wird nach /usr/lib kopiert:

cp libHalloWelt.so /usr/lib/libHalloWelt.so
java HalloWelt

javah in Eclipse ausführen

Lauten den Informationen von hier und hier kann javah als External Tool innerhalb von Eclipse aufgerufen werden.

External Tool konfigurieren

Kofiguration, muss den eigenen Bedürfnissen angepasst werden (Pfad zu javah und Pfad zu den compilierten Klassen):

Location: C:\Program Files\Java\jdk1.8.0_31\bin\javah.exe     
Working Directory: ${workspace_loc:/run/target/classes}        
Arguments: -d "${workspace_loc}${system_property:file.separator}${container_path}" -jni ${java_type_name}

Mit dieser Einstellung wird die Header Datei neben der Java-Source Datei erzeugt und abgelegt.

Links