Java Native Interface – Wikipedia

Im Software-Design ist die Java Native Interface ((JNI) ist ein Programmierframework für Fremdfunktionsschnittstellen, mit dem Java-Code, der in einer Java Virtual Machine (JVM) ausgeführt wird, aufgerufen und von aufgerufen werden kann[1] native Anwendungen (Programme, die für eine Hardware- und Betriebssystemplattform spezifisch sind) und Bibliotheken, die in anderen Sprachen wie C, C ++ und Assembly geschrieben sind.

Ziele[edit]

Mit JNI können Programmierer native Methoden schreiben, um Situationen zu behandeln, in denen eine Anwendung nicht vollständig in der Java-Programmiersprache geschrieben werden kann, z. B. wenn die Standard-Java-Klassenbibliothek die plattformspezifischen Funktionen oder die Programmbibliothek nicht unterstützt. Es wird auch verwendet, um eine vorhandene Anwendung (in einer anderen Programmiersprache geschrieben) so zu ändern, dass sie für Java-Anwendungen zugänglich ist. Viele der Standardbibliotheksklassen hängen von JNI ab, um dem Entwickler und dem Benutzer Funktionen bereitzustellen, z. B. Datei-E / A und Soundfunktionen. Durch die Aufnahme leistungs- und plattformabhängiger API-Implementierungen in die Standardbibliothek können alle Java-Anwendungen sicher und plattformunabhängig auf diese Funktionalität zugreifen.

Mit dem JNI-Framework kann eine native Methode Java-Objekte genauso verwenden, wie Java-Code diese Objekte verwendet. Eine native Methode kann Java-Objekte erstellen und diese Objekte dann untersuchen und zur Ausführung ihrer Aufgaben verwenden. Eine native Methode kann auch Objekte untersuchen und verwenden, die mit Java-Anwendungscode erstellt wurden.

Nur Anwendungen und signierte Applets können JNI aufrufen.

Eine Anwendung, die auf JNI basiert, verliert die von Java angebotene Plattformportabilität (eine teilweise Problemumgehung besteht darin, für jede Plattform eine separate Implementierung von JNI-Code zu schreiben und Java das Betriebssystem erkennen und zur Laufzeit das richtige laden zu lassen).

Native Code-Schnittstelle kann nicht nur mit Java verbunden werden, sondern auch auf Java CanvasDies ist mit der Java AWT Native Interface möglich. Der Prozess ist fast der gleiche, mit nur wenigen Änderungen. Die native Java AWT-Schnittstelle ist erst seit J2SE 1.3 verfügbar.

JNI ermöglicht auch den direkten Zugriff auf Assembly-Code, ohne eine C-Brücke zu durchlaufen.[2] Auf die gleiche Weise ist auch der Zugriff auf Java-Anwendungen von der Assembly aus möglich.[3]

Im JNI-Framework werden native Funktionen in separaten .c- oder .cpp-Dateien implementiert. (C ++ bietet eine etwas einfachere Schnittstelle zu JNI.) Wenn die JVM die Funktion aufruft, übergibt sie a JNIEnv Zeiger, a jobject Zeiger und alle von der Java-Methode deklarierten Java-Argumente. Im Folgenden wird beispielsweise eine Java-Zeichenfolge in eine native Zeichenfolge konvertiert:

extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName
  (JNIEnv *env, jobject obj, jstring javaString)
{
    const char *nativeString = env->GetStringUTFChars(javaString, 0);

    //Do something with the nativeString

    env->ReleaseStringUTFChars(javaString, nativeString);
}

Das env Der Zeiger ist eine Struktur, die die Schnittstelle zur JVM enthält. Es enthält alle Funktionen, die für die Interaktion mit der JVM und die Arbeit mit Java-Objekten erforderlich sind. Beispiel JNI-Funktionen sind das Konvertieren nativer Arrays in / von Java-Arrays, das Konvertieren nativer Zeichenfolgen in / von Java-Zeichenfolgen, das Instanziieren von Objekten, das Auslösen von Ausnahmen usw. Grundsätzlich kann alles verwendet werden, was Java-Code tun kann JNIEnv, wenn auch mit erheblich geringerer Leichtigkeit.

Das Argument obj ist ein Verweis auf das Java-Objekt, in dem diese native Methode deklariert wurde.

Native Datentypen können Java-Datentypen zugeordnet werden. Für zusammengesetzte Typen wie Objekte, Arrays und Zeichenfolgen muss der native Code die Daten explizit konvertieren, indem Methoden in der aufgerufen werden JNIEnv.

Ein JNI-Umgebungszeiger (JNIEnv *) wird als Argument für jede native Funktion übergeben, die einer Java-Methode zugeordnet ist, wodurch die Interaktion mit der JNI-Umgebung innerhalb der nativen Methode ermöglicht wird. Dieser JNI-Schnittstellenzeiger kann gespeichert werden, bleibt jedoch nur im aktuellen Thread gültig. Andere Threads müssen zuerst aufrufen AttachCurrentThread () um sich an die VM anzuschließen und einen JNI-Schnittstellenzeiger zu erhalten. Nach dem Anhängen funktioniert ein nativer Thread wie ein normaler Java-Thread, der innerhalb einer nativen Methode ausgeführt wird. Der native Thread bleibt mit der VM verbunden, bis er aufgerufen wird DetachCurrentThread () sich ablösen.[4]

Das JNI-Framework bietet keine automatische Speicherbereinigung für Nicht-JVM-Speicherressourcen, die durch Code zugewiesen werden, der auf der nativen Seite ausgeführt wird. Folglich übernimmt nativer Seitencode (z. B. Assemblersprache) die Verantwortung für die explizite Freigabe solcher Speicherressourcen, die der native Code erhält.

Wenn sich der native Code auf Linux- und Solaris-Plattformen als Signalhandler registriert, kann er Signale abfangen, die für die JVM bestimmt sind. Mithilfe einer Verantwortungskette kann nativer Code besser mit der JVM zusammenarbeiten. Auf Windows-Plattformen kann SEH (Structured Exception Handling) verwendet werden, um nativen Code in SEH-Try / Catch-Blöcke zu verpacken, um von Maschinen (CPU / FPU) generierte Software-Interrupts (z. B. Verstöße gegen den NULL-Zeigerzugriff und Operationen zum Teilen durch Null) zu erfassen ) und diese Situationen zu behandeln, bevor der Interrupt wieder in die JVM (dh Java-Seitencode) übertragen wird, was aller Wahrscheinlichkeit nach zu einer nicht behandelten Ausnahme führt.[original research?]

Die für die Funktionen NewStringUTF, GetStringUTFLength, GetStringUTFChars, ReleaseStringUTFChars und GetStringUTFRegion verwendete Codierung lautet “UTF-8 geändert”.[5] Das ist nicht für alle Eingaben UTF-8 gültig, aber wirklich eine andere Codierung. Das Nullzeichen (U + 0000) und die Codepunkte, die sich nicht in der mehrsprachigen Grundebene befinden (größer oder gleich U + 10000, dh diejenigen, die als dargestellt sind Ersatzpaare in UTF-16) sind in modifiziertem UTF-8 unterschiedlich codiert. Viele Programme verwenden diese Funktionen tatsächlich falsch und behandeln die zurückgegebenen oder an die Funktionen übergebenen UTF-8-Zeichenfolgen als Standard-UTF-8-Zeichenfolgen anstelle von modifizierten UTF-8-Zeichenfolgen. Programme sollten die Funktionen NewString, GetStringLength, GetStringChars, ReleaseStringChars, GetStringRegion, GetStringCritical und ReleaseStringCritical verwenden, die UTF-16LE-Codierung für Little-Endian-Architekturen und UTF-16BE für Big-Endian-Architekturen verwenden, und dann UTF-16 für UTF-16 verwenden 8 Konvertierungsroutine.[original research?]

Zuordnungstypen[edit]

Die folgende Tabelle zeigt die Zuordnung von Typen zwischen Java (JNI) und nativem Code.

C Typ Java-Sprachtyp Beschreibung Typ Signatur
vorzeichenloser char jboolean vorzeichenlose 8 Bits Z.
signiertes Zeichen jbyte 8 Bit signiert B.
unsigned short jchar vorzeichenlose 16 Bit C.
kurz jshort 16 Bit signiert S.
lange jint vorzeichenbehaftete 32 Bit ich

lang Lang
__int64

jlong 64 Bit signiert J.
schweben jfloat 32 Bit F.
doppelt jdouble 64 Bit D.
Leere V.

Darüber hinaus die Unterschrift "L fully-qualified-class ;" würde die Klasse bedeuten, die durch diesen Namen eindeutig spezifiziert ist; zB die Unterschrift "Ljava/lang/String;" bezieht sich auf die Klasse java.lang.String. Auch Präfix [ to the signature makes the array of that type; for example, [I means the int array type. Finally, a void signature uses the V code.

These types are interchangeable. One can use jint where you normally use an int, and vice versa, without any typecasting required. However, mapping between Java Strings and arrays to native strings and arrays is different. If a jstring is used where a char * would be, the code could crash the JVM.[original research?]

Performance[edit]

JNI verursacht unter bestimmten Umständen erhebliche Gemeinkosten und Leistungseinbußen:[6]

  • Funktionsaufrufe an JNI-Methoden sind teuer, insbesondere wenn eine Methode wiederholt aufgerufen wird.
  • Native Methoden werden weder von der JVM eingebunden, noch kann die Methode JIT-kompiliert werden, da die Methode bereits kompiliert ist.
  • Ein Java-Array kann für den Zugriff in nativem Code kopiert und später zurückkopiert werden. Die Kosten können in der Größe des Arrays linear sein.
  • Wenn der Methode ein Objekt übergeben wird oder ein Rückruf erforderlich ist, führt die native Methode wahrscheinlich eigene Aufrufe an die JVM durch. Der Zugriff auf Java-Felder, -Methoden und -Typen über den nativen Code erfordert etwas Ähnliches wie Reflektion. Signaturen werden in Zeichenfolgen angegeben und von der JVM abgefragt. Dies ist sowohl langsam als auch fehleranfällig.
  • Java-Strings sind Objekte, haben eine Länge und sind codiert. Für den Zugriff auf oder das Erstellen einer Zeichenfolge ist möglicherweise eine O (n) -Kopie erforderlich.

Alternativen[edit]

Microsofts proprietäre Implementierung einer Java Virtual Machine (Visual J ++) hatte einen ähnlichen Mechanismus zum Aufrufen von nativem Code aus Java, den so genannten Raw Native Interface ((RNI). Darüber hinaus war es einfach, vorhandenen nativen Code aufzurufen, der Java selbst nicht kannte, wie beispielsweise die aufgerufene Windows-API (ohne darauf beschränkt zu sein) J / Direct. Nach dem Sun-Microsoft-Rechtsstreit über diese Implementierung wird Visual J ++ jedoch nicht mehr beibehalten.

Die Verwendung von RNI war weniger umständlich als die von JNI, da keine Buchhaltung mit einem Java-Umgebungszeiger erforderlich war. Stattdessen konnte direkt auf alle Java-Objekte zugegriffen werden. Um dies zu erleichtern, wurde ein Tool verwendet, das Header-Dateien aus Java-Klassen generiert. In ähnlicher Weise war J / Direct einfacher zu verwenden als die erforderliche native Zwischenbibliothek und JNI, obwohl JNA derzeit eine Alternative ist.[original research?]

Siehe auch[edit]

Verweise[edit]

Literaturverzeichnis[edit]

Externe Links[edit]