JNI verbindet Java mit den systemnahen Programmiersprachen C und C++, indem es Aufrufe in beiden Richtungen erlaubt.
Nicht ganz minimal und ziemlich sinnlos, aber interessant.
Das Beispiel ruft eine C-Funktion auf, welche wiederum die
Methode System.out.println verwendet, um den
bekannten Gruß auszugeben.
public class Hello {
public static void main (String[] args) {
new Hello().print();
}
private native void print ();
static { System.loadLibrary ("Hello"); }
}
Anschließend übersetzt man dieses Java-Programm und extrahiert eine Header-Datei:
class=Hello javac $class.java javah -jni $class
Jetzt fehlt nur noch die Implementierung der soeben erzeugten Schnittstelle in C:
#include "Hello.h"
#include <stdio.h>
JNIEXPORT void JNICALL
Java_Hello_print (JNIEnv * env, jobject self)
{
printf ("Hello, C!\n");
jclass system = (*env)->FindClass (env, "java/lang/System");
jfieldID id = (*env)->GetStaticFieldID (env, system, "out", "Ljava/io/PrintStream;");
jobject obj = (*env)->GetStaticObjectField (env, system, id);
jclass cls = (*env)->GetObjectClass (env, obj);
jmethodID println = (*env)->GetMethodID (env, cls, "println", "(Ljava/lang/String;)V");
jobject hello = (*env)->NewStringUTF (env, "Namaste, Java!");
// Call java.lang.System.out.println (hello);
(*env)->CallVoidMethod (env, obj, println, hello);
printf ("Goodbye, C!\n");
}
Der Übersetzer erzeugt aus dieser Datei eine dynamisch ladbare
Bibliothek namens libHello.so, welche die
JVM
laden und verwenden kann.
gcc -g -Wall -fPIC -I/usr/lib/jvm/java-7-openjdk-amd64/include -c -o $class.o $class.c gcc -lc $class.o -shared -W1,soname,$class -o lib$class.so java -Djava.library.path=. $class Hello, C! Namaste, Java! Goodbye, C!
Ein Felddeskriptor identifiziert Parameter, Rückgabewert und Methoden-Signatur.
| Deskriptor | Type | NativeType | Beschreibung |
| Void | |||
| Z | Boolean | jboolean | Wahrheitswert |
| B | Byte | jbyte | Speicherzelle |
| C | Char | jchar | Unicodepunkt |
| S | Short | jshort | Kleine Zahl (16 Bit) |
| I | Int | jint | Zahl (32 Bit) |
| J | Long | jlong | Große Zahl (64 Bit) |
| F | Float | jfloat | Ungenaue Gleitpunktzahl |
| D | Double | jdouble | Gleitpunktzahl |
| LPackage/…/Object | Object | jobject | Objekt |
| [Field | Array | Reihung | |
| (Field,…)ReturnType | Method | Methode |
Die Klasse JNIEnv dient als Schnittstelle zur Java
Laufzeitumgebung. Sie ermöglicht es, Klassen zu erzeugen, zu suchen,
zu laden, zu modifizieren und Methoden aufzurufen.
| JNIEnv | |||
| jint | GetVersion | () | |
| jint | GetJavaVM | (JavaVM **) | |
| Klasse | |||
|---|---|---|---|
| jclass | DefineClass | (const char * class, jobject loader, jbyte buf, jsize len) | |
| jclass | FindClass | (const char * class) | |
| jclass | GetSuperclass | (jclass) | |
| jboolean | IsAssignableFrom | (jclass, jclass) | |
| Objekt | |||
| jobject | AllocObject | (jclass) | |
| jobject | NewObject | (jclass, jmethodID constructor, ...) | |
| jclass | GetObjectClass | (jobject) | |
| jboolean | IsInstanceOf | (jobject, jclass) | |
| jboolean | IsSameObject | (jobject, jobject) | |
| Feld | |||
| jfieldID | GetFieldID | (jclass, const char * name, const char * field) | |
| jfieldID | GetStaticFieldID | (jclass, const char * name, const char * field) | |
| NativeType | GetTypeField | (jobject, jfieldID) | |
| SetTypeField | (jobject, jfieldID, NativeType) | ||
| NativeType | GetStaticTypeField | (jclass, jfieldID) | |
| SetStaticTypeField | (jclass, jfieldID, NativeType) | ||
| Methode | |||
| jmethodID | GetMethodID | (jclass, const char * name, const char * method) | |
| jmethodID | GetStaticMethodID | (jclass, const char * name, const char * method) | |
| NativeType | CallStaticTypeMethod | (jclass, jmethodID, ...) | |
| NativeType | CallTypeMethod | (jobject, jmethodID, ...) | |
| NativeType | CallTypeMethodA | (jobject, jmethodID, jvalue *) | |
| NativeType | CallTypeMethodV | (jobject, jmethodID, va_list) | |
| NativeType | CallNonvirtualTypeMethod | (jobject, jclass, jmethodID) | |
| Zeichenkette | |||
| jstring | NewString | (const jchar *, jsize) | |
| jstring | NewStringUTF | (const char *) | |
| jsize | GetStringLength | (jstring) | |
| jsize | GetStringLengthUTF | (jstring) | |
| const jchar * | GetStringChars | (jstring, jboolean *) | |
| const jbyte * | GetStringUTFChars | (jstring, jboolean *) | |
| const jchar * | GetStringCritical | (jstring, jboolean *) | |
| GetStringRegion | (jstring, jsize start, jsize len, jchar * buf) | ||
| GetStringUTFRegion | (jstring, jsize start, jsize len, jchar * buf) | ||
| ReleaseStringChars | (jstring, const jchar *) | ||
| ReleaseStringCritical | (jstring, const jchar *) | ||
| ReleaseStringUTFChars | (jstring, const char *) | ||
| Reihung | |||
| jarray | NewObjectArray | (jsize, jclass, jobject) | |
| ArrayType | NewTypeArray | (jsize) | |
| jsize | GetArrayLength | (jarray) | |
| NativeType | GetTypeArrayElements | (ArrayType, jboolean *) | |
| GetTypeArrayRegion | (ArrayType, jsize start, jsize len, NativeType * buf) | ||
| SetTypeArrayRegion | (ArrayType, jsize start, jsize len, NativeType * buf) | ||
| GetTypeField | (ArrayType, jfieldID) | ||
| jobject | GetObjectArrayElement | (jobjectArray, jsize) | |
| SetObjectArrayElement | (jobjectArray, jsize, jobject) | ||
| void * | GetPrimitiveArrayCritical | (jarray, jboolean *) | |
| ReleasePrimitiveArrayCritical | (jarray, void *, jint mode) | ||
| ReleaseTypeArrayElements | (ArrayType, NativeType *, jint mode) | ||
| Ausnahme | |||
| jint | Throw | (jthrowable) | |
| ThrowNew | (jclass, const char *) | ||
| jthrowable | ExceptionOccurred | () | |
| ExceptionDescribe | () | ||
| jboolean | ExceptionCheck | () | |
| jint | ExceptionClear | (jint) | |
| FatalError | (const char *) | ||
| Verweis | |||
| jobject | NewLocalRef | (jobject) | |
| jobject | NewGlobalRef | (jobject) | |
| jweak | NewWeakGlobalRef | (jobject) | |
| DeleteLocalRef | (jobject) | ||
| DeleteGlobalRef | (jobject) | ||
| DeleteWeakGlobalRef | (jobject) | ||
| Reflexion | |||
| jfieldID | FromReflectedField | (jobject) | |
| jmethodID | FromReflectedMethod | (jobject) | |
| jobject | ToReflectedField | (jclass, jfieldID, jboolean) | |
| jobject | ToReflectedMethod | (jclass, jmethodID, jboolean) | |
| Sonstiges | |||
| RegisterNatives | (jclass, const JNINativeMethod *, jint) | ||
| jint | UnregisterNatives | (jclass) | |
| jint | MonitorEnter | (jobject) | |
| jint | MonitorExit | (jobject) | |
| jint | EnsureLocalCapacity | (jint) | |
| jint | PushLocalFrame | (jint) | |
| jobject | PopLocalFrame | (jobject) | |
META-INF| Datum | Version | Codename | Neuerungen |
| 1995 | JDK Beta | - | Entwicklungsversionen |
| 1996-01-23 | JDK 1.0 | Oak | Erstveröffentlichung |
| 1997-02-19 | JDK 1.1 | - | Innere Klassen, AWT, RMI, JDBC |
| 1998-12-08 | J2SE 1.2 | Playground | Swing, CORBA & IDL |
| 2000-05-08 | J2SE 1.3 | Kestrel | HotSpot JVM |
| 2002-02-06 | J2SE 1.4 | Merlin | Parser und Werkzeuge für XML |
| 2004-09-30 | J2SE 5.0 | Tiger | Generics, Annotations, Autoboxing, Enumerations |
| 2006-12-11 | Java SE 6 | Mustang | Übernahme durch Oracle, Leistungsoptimierung |
| 2011-07-28 | Java SE 7 | Dolphin | NIO, Unterstützung dynmaischer Sprachen |
| 2014-03-18 | Java SE 8 | - | Lambda-Ausdrücke |