3. JNI-Erweiterungen im JDK 1.2
NEXT |
PREVIOUS |
CONTENT
Library- and Version Management
- Im JKD 1.1 ist es möglich gewesen, einmal geladene Bibliotheken von jedem classloader aus
zu sehen. Dabei kann eine Programmbibliothek versehentlich mit einer Klasse selben Namens in einem
anderen classloader gelinkt werden, bzw. native Mehtoden können leicht Klassen in
verschiedenen classloadern vertauschen.
- Im JDK 1.2 ist dies nicht mher möglich. man kann ein und dieselbe native Bibliotheken
nicht mehr mit mehr als einen classloader laden. Das verursacht einen
UnsatisfiedLinkError
- Vorteile:
- Namespace separation wird erhalten
- Bibliotheken können aus dem Speicher entfernt werden, wenn der entsprechende classloader
vom GC entfernt wird.
- Versionskontrolle:
- neue Funktion
jint JNI_OnLoad(JavaVM *vm, void *reserved)
wird von der JVM aufgerufen, wenn die Bibliothek geladen wurde. Sie muß
von der Bibliothek exportiert werden und liefert die
Version, die die Bibliothek benötigt. Wenn die Bibliothek irgendeines der neuen JDK 1.2
features nutzen will, muß sie diese Funktion exportieren und sie muß die Version
JNI_VERSION_1_2
zurückliefern; Tut sie dies nicht, nimmt die JVM an, daß
sie nur die features aus dem JDK 1.1 nutzt (JNI_VERSION_1_1
)
- neue Funktion
void JNI_OnUnload(JavaVM *vm, void *reserved)
wird von der vm aufgerufwn, wenn die native Bibliothek garbage collected wurde
- neue Konstanten:
#define JNI_VERSION_1_1 0x00010001
#define JNI_VERSION_1_2 0x00010002
Managment lokaler Referenzen
- wie schon erwähnt: lokale Referenzen benötigen Platz (siehe 2.)
- in JDK 1.1 gab es JNI-Funktionen
DeleteLocalRef
für das "manuelle" löschen
von lokalen Referenzen
- in JDK 1.2 neu:
jint EnsureLocalCapacity(JNIEnv *env, jint capacity)
liefert zurück, ob eine bestimmte
Anzahl von lokalen Referenzen erzeugt werden kann, ohne Speicherprobleme zu bekommen.
Wenn erfolgreich liefert sie 0 sonst wird ein OutOfMemoryError
geschmissen
und ein negativer Wert zurückgegeben. Standardmäßig können in einer
native Methode 16 lok. Referenzen erzeugt werden.
ACHTUNG ! Es werden auch jenseits der erfragten Kapazität lokale Referenzen erzeugt
JNI-Debugging: -verbose:jni
auf der Kommandozeile angeben -> viel information
jint PushLocalFrame(JNIEnv *env, jint capacity)
erzeuegt einen neuen sogenannten local reference frame, in dem mindestens die angegebne
Anzahl von lokalen Referenzen erzeugt werden kann. Wenn erfolgreich liefert sie 0 sonst
wird ein OutOfMemoryError
geschmissen und ein negativer Wert zurückgegeben.
Schon erzeugte lokale Referenzen bleiben weiterhin gültig.
jobject PopLocalFrame(JNIEnv *env, jobject result)
löscht den aktuellen
local reference frame und alle darin enthaltenen lokalen Referenzen und liefert eine
lokale Referenz für das übergebene Objekt an den vorherigen local reference frame
jobject NewLocalRef(JNIEnv *env, jobject ref)
erzeugt eine neue lokale Referenz
zu dem objekt, auf das die übergeben referenz zeigt.
Exceptions
- neue "Bequemlichkeitsfunktion"
jboolean ExceptionCheck(JNIEnv *env)
prüft ob eine
nicht gehandelte Exception existiert, ohne vorher eine lokale referenz auf das Objekt zu
erzeugen. Liefert JNI_TRUE
oder JNI_FALSE
.
Arrayoperationen
- JDK 1.1:
Get/ReleaseArrayElements
Funktionen, um die Elemente von Primitiv-Arrays zu
holen. Je nach JVM mit oder ohne pinning wird ein Zeiger auf die originalen Daten oder eine Kopie
dieser geliefert.
- JNK 1.2
void * GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)
liefern in jedem Fall einen direkten Zeiger auf die Daten.
Einschränkungen:
- Code zwischen diesen beiden Funktionen ist in einem "kritischen Abschnitt" und darf nicht
lange laufen
- es dürfen keine JNI-Funktionen aufgerufen werden
- es dürfen keine Systemrufe aufgerufen werden, die den aktuellen Thread schlafen legen,
z.b. read( ) auf eine stream, der von einem anderen java Thread beschrieben wird
- mehrfache solche Funktionspaare können ineinander geschachtelt werden
Stringoperationen
- neue Funktionen
void GetStringRegion(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf)
kopiert aus dem angegebenen String eine bestimmte Anzahl von UNICODE Characters ab Offset
start in den angegebenen Buffer
void GetStringUTFRegion(JNIEnv *env, jstring str, jsize start, jsize len, char *buf)
konvertiert aus dem angegebenen String ab Offset start eine bestimmte Anzahl von UNICODE
Characters in UTF-8-Format und speichert diese in Puffer buf
const jchar * GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy)
void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *carray)
dienen dem ermitteln der einzelnen Characters aus einem String (wie Get/ReleaseStringChars
,
die schon aus dem JDK 1.1 bekannt sind). Sie besitzen die selben Einschränkungen wie
die im vorigen Abschnitt vorgestellten Funktionen Get/ReleasePrimitiveArrayCritical
Reflection
- Reflection heißt, daß man während der Laufzeit Java-Klassen untersuchen kann und
Informationen über ihre Struktur bekommen kann.
- Als Reflection Unterstützung im JNI werden Funktionen eingeführt, die zwischen field und method
IDs im JNI und field und method objects in der Reflection Core API konvertieren können.
neue Funktionnen:
jmethodID FromReflectedMethod(JNIEnv *env, jobject method)
konvertiert java.lang.reflect.Method oder java.lang.reflect.Constructor in eine jmethodId
jfieldID FromReflectedField(JNIEnv *env, jobject field)
konmvertiert java.lang.reflect.Field in eine jfieldId
jobject ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID methodID)
konvertiert eine jmethodeId in java.lang.reflect.Method oder java.lang.reflect.Constructur
jobject ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID)
konvertiert eine jfieldId in java.lang.reflect.Field
© 1999 Lars Jordan,
Chemnitz Java User Group