Java Native Interface Eine Einführung.

Slides:



Advertisements
Ähnliche Präsentationen
M a r c – o l i v e r p a h l Informatik I – Kapitel 7 Klassen und höhere Datentypen Zusammenfassung des Kapitel 7 Küchlin, Weber, Einführung in die Informatik,
Advertisements

der Universität Oldenburg
der Universität Oldenburg
Objektorientierte Programmierung
der Universität Oldenburg
der Universität Oldenburg
DVG Dateien Dateien. DVG Dateien 2 Die Klasse File Die Klasse File stellt die Verbindung zwischen dem Filesystem des Rechners und dem.
DVG Einfache Klassen Einfache Klassen. DVG Einfache Klassen 2 Strukturen Beispiel: Personendaten bestehen aus –String name –String vorname.
PKJ 2005/1 Stefan Dissmann Vorwoche - Klasse public class Studierende { private String name, vorname, studiengang; private int matNr, semester; private.
Zusammenfassung des Kapitels 8
Verteilte Software - Java - Prozedurale Programmierung 1
Objektrelationales Mapping mit JPA Entity Mapping Jonas Bandi Simon Martinelli.
Binäre Bäume Richard Göbel.
Java: Objektorientierte Programmierung
Java: Dynamische Datentypen
Listen Richard Göbel.
Indirekte Adressierung
Java: Grundlagen der Sprache
Java: Referenzen und Zeichenketten
Java: Grundlagen der Objektorientierung
Praktikum Entwicklung und Einsatz von Geosoftware I - Sitzung 3 Klassen, Objekte, Arrays und Kontrollstrukturen Sommersemester 2003 Lars Bernard.
Dynamische Webseiten Java servlets.
Objektorientierte Programmierung JDK-Klassenbibliothek
Java-Kurs - 2. Übung Entwicklungsumgebung Struktur von Programmen
PRJ 2007/1 Stefan Dissmann Motivation Problem: gleiche Datenstrukturen werden für verschiedene Objekte gebraucht: z.B. Listen von Studierenden, Kunden,
PKJ 2005/1 Stefan Dissmann Ausblick Es fehlen noch: Möglichkeiten zum Strukturieren größerer Programme Umgang mit variabler Zahl von Elementen Umgang mit.
PKJ 2005/1 Stefan Dissmann Rückblick auf 2005 Was zuletzt in 2005 vorgestellt wurde: Klassen mit Attributen, Methoden und Konstruktoren Referenzen auf.
PKJ 2005/1 Stefan Dissmann Zusammenfassung Bisher im Kurs erarbeitete Konzepte(1): Umgang mit einfachen Datentypen Umgang mit Feldern Umgang mit Referenzen.
PKJ 2005/1 Stefan Dissmann Zusammenfassung Vorwoche Methoden sind mit einem Namen versehene Programmabschnitte besitzen Rückgabetyp, Namen, Parameterliste.
Abstrakter Datentyp in C++ I - Klasse -
Programmiermethodik SS2010 © 2010 Albert Zündorf, University of Kassel 1 Gesamtvorgehen 1. Textuelle Szenarios 2. Objektdiagramme 3. Klassendiagramm 4.
Proxy Pattern Vorlesung Design Patterns Sieglinde Heinrich
F açade P attern By Nicolas Lanquetin. Façade Pattern Structural Pattern Bietet ein gemeinsames Interface, anstatt vieler Interfaces eines Subsystems.
1EDV 1 - Java Native Interface Java mit eingebundenen (native) C-Programme Vortrag: Rolf Heitzenröder am
Modulare Programmierung
DVG Einführung in Java1 Einführung in JAVA.
DVG Einfache Klassen 1 Einfache Klassen. 2DVG Einfache KlassenStrukturen Beispiel: Personendaten bestehen aus String name String name.
DVG Verkettete Listen Verkettete Listen. DVG Verkettete Listen 2 Primitive Datentypen Vorteile: –werden direkt vom Prozessor unterstützt.
Java in 9 Folien Besser: Online-Buch Go to Java 2.
Einführung in die Programmierung Datensammlung
Thema: Fibonacci-Zahlen
Seite 1 Interface - Konzept Ein Interface führt einen neuen Datentyp ein: interface Frau {... } Das Interface enthält Deklarationen ( keine Definitionen.
Objektorientierte Modellierung
PRJ 2007/1 Stefan Dissmann Verkettete datenstruktur: Liste Problem: Liste, die eine beliebige Zahl von Elementen verwaltet Operationen: Erzeugen, Anfügen,
Rekursive Funktionen (Fakultät)
OO implementieren Teil IV Objekte erzeugen. © René ProbstModul 226IV - 2 Von der Klasse zum Objekt Plan Bau Objekt Klasse Instanzierung Objekt Das Objekt.
Java Performance Tuning Performance Tuning is similar to playing a strategy game but happily you usually get paid for it.
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
Entity Mapping Persistente Domänenmodelle mit JPA 2.0 und Bean Validation.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fakultät.
Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung) (Vorlesung) Prof. Dr. Günter Rudolph Fachbereich.
Kap 4-1OHO Kap. 4.2 Das Orbix CORBA-System Kurzer überblick zu der CORBA-Implementierung Orbix •Unser Fahrplan: •IDL Verwendungsbeispiel •Zoom-In: CORBA.
Exception Handling in Java
Equals, Hashcode und CompareTo Micha Kessler
Dynamische Datentypen
CuP - Java Eingabe über Tastatur, AudioClips, überschreiben, Quiz Montag, 18. November 2002.
Objektorientiertes Konstruieren
Common Language Runtime Seminar Softwareentwicklung Wintersemester 2003 Gertraud Orthofer
CuP - Java Vierte Vorlesung Entspricht ungefähr Kapitel 2.1 des Skriptums Montag, 14. Oktober 2002.
Learning By Doing Ausnahmebehandlung Exceptions (Ausnahmebehandlung) Typische Fehlverhalten zur Laufzeit: s. Buch S. 287ff -Verwendung von null-Objekten.
Learning By Doing Konstruktoren Gleicher Name wie die Klasse Zur Initialisierung des Objekts, insbesondere mit Parametern Wir immer bei der Objekterzeugung.
Programmierung von Agenten in Java: Implementierung einer Supply-Chain
Lind 02/2005 Einführung in JAVA. Lind 02/2005 Beispiel: Mittelwert Es soll ein Programm erstellt werden, das den Mittelwert zweier reeller Zahlen berechnet.
Programmiervorkurs WS 2014/15 Methoden
Programmiervorkurs WS 2014 Referenzdatentypen
CuP - Java Achte Vorlesung Entspricht ungefähr Kapitel 4.1 des Skriptums Montag, 28. Oktober 2002.
3. Beschreibung von Abläufen durch Algorithmen 3.4 Zufall
Alois Schütte Advanced System Programming 2 Interprozeßkommunikation  2.1 JVM Ablaufumgebung  2.2 Java Native Interface (JNI)  Verwendung von.
Übung Informatik I exercise01. 2 Inhaltsübersicht Nachbesprechung Übung 1 Individuelle Fragen/Bemerkungen.
Java Programme nur ein bisschen objektorientiert.
 Präsentation transkript:

Java Native Interface Eine Einführung

Motivation Java: abstrahiert von Hardware und Betriebssystem + hohe Portabilität + hohe Sicherheit (Sandbox-Prinzip) - verminderte Performanz (mit heutigen JIT-Compilern i.A. kein Problem mehr) - kein direkter Zugriff auf Hardware-/Betriebssystem C/C++: Programmiersprache für OS-Entwicklung (UNIX) + maschinennah, hohe Performanz + alt, weit verbreitet, umfangreiche Sammlung von Legacy-Code - Programmierung möglicherweise umständlich (GUI in C?) - hohe Anforderungen an Programmierer

Das Java Native Interface (JNI) Schnittstelle, um C/C++ -Code in Java einzubinden und umgekehrt Beispiele - C/C++ in Java: Treiber, Betriebssystemfunktionen ansprechen (SWT) Vorhandene Bibliotheken einbinden Zeitkritische Funktionen in C oder Assembler einbinden  Möglicherweise Verlust der Portabilität! Beispiel – Java in C/C++: Browser, der Applets ausführt

JNI - Architektur Schnittstelle definiert Datentypen und Funktionen… zum Aufruf nativer Funktionen in Java zur Abbildung von Java-Datentypen in C/C++ zur Erzeugung und Mani- pulation von Java-Objekten in C/C++ (OO in C?) zum Aufruf einer JVM aus C/C++ heraus

C in Java : Hallo Welt Minimal-Beispiel: Aufruf einer nativen Methode, die „Hallo Welt!“ auf der Konsole ausgibt. Prinzipielles Vorgehen (immer gleich):

Hallo Welt – Java-Code Definition einer nativen Methode ohne Rumpf Dynamisches Laden der Bibliothek, die Methode bereitstellt Kompilieren mit: javac HelloWorld.java class HelloWorld { private native void print(); public static void main(String[] args) { new HelloWorld().print(); } static { System.loadLibrary("HelloWorld"); }

Hallo Welt – C/C++-Header Die C-Methode, die in HelloWorld aufgerufen wird, muss gewisse Konventionen erfüllen javah –jni HelloWorld.class erzeugt Header-Datei HelloWorld.h mit Prototypen aller nativen Methoden: Methoden-Name muss in C eindeutig sein, daher: Java_packageName_className_methodName Parameterlose Funktion print() erhält in C zwei Parameter !? include <jni.h> […] JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *env, jobject); […]

Hallo Welt – C-Code Implementierung der in Header-Datei definierten Funktion in Datei HelloWorld.c: Übersetzen in gemeinsam genutzte Bibliothek gcc -fPIC -c HelloWorld.c ld -shared -soname libHelloWorld.so.l -o libHelloWorld.so HelloWorld.o #include "HelloWorld.h" #include <stdio.h> JNIEXPORT void JNICALL Java_HelloWorld_print (JNIEnv *env, jobject obj){ printf("Hallo Welt!\n"); }

Hallo Welt - Finale Ausführen des Java-Programms: java HelloWorld java.lang.UnsatisfiedLinkError: no HelloWorld in library path at java.lang.Runtime.loadLibrary(Runtime.java) at java.lang.System.loadLibrary(System.java) at HelloWorld.main(HelloWorld.java)  Pfad zur Bibliothek noch unbekannt! Entweder Bibliothek in /usr/lib verschieben (root-Rechte!), setenv LD_LIBRARY_PATH .:${LD_LIBRARY_PATH}, oder Bibliothekpfad explizit an Java übergeben: java –Djava.library.path=. HelloWorld

Abbildung der Datentypen Bisher: kein Datenaustausch zwischen Java und C Datentypen in Java: Primitive Datentypen, Klassen, Objekte, Arrays Unterschiede Java vs. C: Java: Einheitliche Spezifikation primitiver Datentypen auf allen Plattformen C: plattformabhängig (z.B. 2Byte int, 4Byte int) Java: Objektorientierung C: keine Objekte, aber strukturierte Datentypen und Funktionszeiger

Abbildung primitiver Datentypen Java-Typ Nativer Typ Beschreibung boolean jboolean 8 Bit ohne Vorzeichen byte jbyte 8 Bit mit Vorzeichen char jchar 16 Bit ohne Vorzeichen short jshort 16 Bit mit Vorzeichen int jint 32 Bit mit Vorzeichen long jlong 64 Bit mit Vorzeichen float jfloat 32 Bit double jdouble 64 Bit void

Abb. primitiver Datentypen – Beispiel public class Sum{ static{ System.loadLibrary("Sum"); } public static native int sum(int a, int b); public static void main(String[] args){ System.out.println("sum(3,4)=" + sum(3,4)); }} #include <jni.h> […] JNIEXPORT jint JNICALL Java_Sum_sum (JNIEnv *env, jclass, jint, jint); […] JNIEXPORT jint JNICALL Java_Sum_sum(JNIEnv *env, jclass cl, jint a, jint b){ jint result = a + b; return result; }

Abbildung von Referenz-Datentypen Objekte, Klassen und Arrays werden in Java über Referenzen angesprochen An C wird ein „transparenter“ Pointer übergeben, der auf die Objekte in der JVM zeigt. Zugriff auf die Objekte erfolgt immer über die JNIEnv-Umgebung, die jeder nativen Methode übergeben wird:

Abb. von Referenztypen – z.B. Arrays import java.util.Random; public class Sort{ static{ System.loadLibrary("QSort"); } public static native void sort(double[] arr); public static void main(String[] args){ […] double[] arr = new double[Integer.parseInt(args[0])]; Random r = new Random(); for(int i=0; i< arr.length; arr[i++] = r.nextInt(10000)); long s = System.currentTimeMillis(); sort(arr); long e = System.currentTimeMillis(); System.out.println("Sortierung dauerte "+(e-s)+"ms"); }

Abb. von Referenztypen – z.B. Arrays Prototyp: Zugriff auf Array-Elemente: JNIEXPORT void JNICALL Java_Sort_sort (JNIEnv *env, jclass, jdoubleArray); JNIEXPORT void JNICALL Java_Sort_sort (JNIEnv *env, jclass cl, jdoubleArray arr){ jdouble *cArray = (jdouble*) arr; // FALSCH!!! // arr ist lediglich ein Pointer auf eine JVM- // Datenstruktur. Der Zugriff auf die Array-Elemente // muss über die JNIEnv Umgebung erfolgen! […] }

Abb. von Referenztypen – z.B. Arrays int compare(const void *a, const void *b){ return *((jdouble*) a) < *((jdouble*) b) ? -1 : +1; } JNIEXPORT void JNICALL Java_Sort_sort (JNIEnv *env, jclass cl, jdoubleArray arr){ jboolean isCopy; jdouble* cArray = (*env)->GetDoubleArrayElements(env, arr, isCopy); jint length = (*env)->GetArrayLength(env, array); qsort(cArray, length, sizeof(jdouble), &compare); if(isCopy) (*env)->ReleaseDoubleArrayElements(env, array, cArray, 0);

Array-Zugriffsmethoden Get<Type>ArrayRegion, Set<Type>ArrayRegion Kopiert Bereich aus oder in ein Array mit primitivem Datentyp Get<Type>ArrayElements, Release<Type>ArrayElements Erhält einen Pointer auf ein Array (ggf. auch Kopie) und gibt ihn wieder frei (ansonsten Speicherleck!) GetArrayLength Ermittelt die Länge eines Arrays New<Type>Array Legt ein neues Array an Nur auf primitive Arrays anwendbar!

Zugriff auf Objekt-Arrays Beispiel: String[] strArray; int[][] intArray; Object[] objArray; Unmöglich, gesamtes Array abzufragen Lediglich einzelne Einträge zugreifbar GetObjectArrayElement SetObjectArrayElement

Beispiel: Anlegen eines 2D-Feldes private static native int[][] initInt2DArray(int size); Zuerst: Anweisung an JVM, ein int[] array anzulegen: JNIEXPORT jobjectArray JNICALL Java_ObjectArrayTest_initInt2DArray(JNIEnv *env, jclass c, int s){ jobjectArray result; int i; jclass intArrCls = (*env)->FindClass(env, "[I"); if (intArrCls == NULL) return NULL; /* exception thrown */ result = (*env)->NewObjectArray(env, size, intArrCls, NULL); if (result == NULL) return NULL; /* out of memory error thrown */ …

Beispiel: Anlegen eines 2D-Feldes Dann: Für jeden Eintrag des int[] Arrays ein primitives int[] Array anlegen … for (i = 0; i < size; i++) { jint tmp[256]; /* make sure it is large enough! */ int j; jintArray iarr = (*env)->NewIntArray(env, size); if (iarr == NULL) return NULL; /* out of memory error */ for (j = 0; j < size; j++) tmp[j] = i + j; (*env)->SetIntArrayRegion(env, iarr, 0, size, tmp); (*env)->SetObjectArrayElement(env, result, i, iarr); (*env)->DeleteLocalRef(env, iarr); } return result;

Beispiel: Anlegen eines 2D-Feldes Dann: Für jeden Eintrag des int[] Arrays ein primitives int[] Array anlegen … for (i = 0; i < size; i++) { jint tmp[256]; /* make sure it is large enough! */ int j; jintArray iarr = (*env)->NewIntArray(env, size); if (iarr == NULL) return NULL; /* out of memory error */ for (j = 0; j < size; j++) tmp[j] = i + j; (*env)->SetIntArrayRegion(env, iarr, 0, size, tmp); (*env)->SetObjectArrayElement(env, result, i, iarr); (*env)->DeleteLocalRef(env, iarr); } return result; Inhalt von tmp nach iarr kopieren

Beispiel: Anlegen eines 2D-Feldes Dann: Für jeden Eintrag des int[] Arrays ein primitives int[] Array anlegen … for (i = 0; i < size; i++) { jint tmp[256]; /* make sure it is large enough! */ int j; jintArray iarr = (*env)->NewIntArray(env, size); if (iarr == NULL) return NULL; /* out of memory error */ for (j = 0; j < size; j++) tmp[j] = i + j; (*env)->SetIntArrayRegion(env, iarr, 0, size, tmp); (*env)->SetObjectArrayElement(env, result, i, iarr); (*env)->DeleteLocalRef(env, iarr); } return result; Array an übergeordnetes Objekt-Array result übergeben

Beispiel: Anlegen eines 2D-Feldes Dann: Für jeden Eintrag des int[] Arrays ein primitives int[] Array anlegen … for (i = 0; i < size; i++) { jint tmp[256]; /* make sure it is large enough! */ int j; jintArray iarr = (*env)->NewIntArray(env, size); if (iarr == NULL) return NULL; /* out of memory error */ for (j = 0; j < size; j++) tmp[j] = i + j; (*env)->SetIntArrayRegion(env, iarr, 0, size, tmp); (*env)->SetObjectArrayElement(env, result, i, iarr); (*env)->DeleteLocalRef(env, iarr); } return result; Kontrolle über iarr an JVM geben

Arbeiten mit Strings Java Strings sind Unicode-Codiert, C-Strings sind ASCII-codiert Anbindung über UTF-8 (kann beide Codierungen abbilden) GetStringChars, ReleaseStringChars GetStringUTFChars, ReleaseStringUTFChar GetStringLength, GetStringUTFLength NewString, NewStringUTF GetStringRegion, SetStringRegion GetStringUTFRegion, SetStringUTFRegion Anbindung sehr umständlich, Java im Umgang mit Strings komfortabler, daher wenig Relevanz

Zugriff auf Objekt-Felder und -Methoden Bei komplexen Klassen-Instanzen kann aus C heraus auf die Felder und Methoden der Instanz zugegriffen werden. Mechanismus erscheint relativ umständlich, daher hier nur exemplarisch dargestellt. Für nähere Infos siehe JNI-Referenz

Zugriff auf Static-Feld Java-Klasse mit statischem Feld si si soll in nativer Methode manipuliert werden class StaticFieldAccess { private static int si; private native void accessField(); public static void main(String args[]) { StaticFieldAccess c = new StaticFieldAccess(); StaticFieldAccess.si = 100; c.accessField(); System.out.println("In Java:"); System.out.println(" StaticFieldAccess.si = " + si); } static { System.loadLibrary("StaticFieldAccess"); }

Zugriff auf Static-Feld JNIEXPORT void JNICALL Java_StaticFieldAccess_accessField(JNIEnv *env, jobject obj){ jfieldID fid; /* store the field ID */ jint si; /* Get a reference to obj’s class */ jclass cls = (*env)->GetObjectClass(env, obj); /* Look for the static field si in cls */ fid = (*env)->GetStaticFieldID(env, cls, "si", "I"); if (fid == NULL) return; /* field not found */ /* Access the static field si */ si = (*env)->GetStaticIntField(env, cls, fid); printf(" StaticFieldAccess.si = %d\n", si); (*env)->SetStaticIntField(env, cls, fid, 200); }

Zugriff auf Instanz-Methode Methode callback() soll in nativeMethod() gerufen werden class InstanceMethodCall { private native void nativeMethod(); private void callback() { System.out.println("In Java"); } public static void main(String args[]) { InstanceMethodCall c = new InstanceMethodCall(); c.nativeMethod(); static { System.loadLibrary("InstanceMethodCall");

Zugriff auf Instanz-Methode JNIEXPORT void JNICALL Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj){ jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V"); if (mid == NULL) return; /* method not found */ printf("In C\n"); (*env)->CallVoidMethod(env, obj, mid); }

Diese Themen werden dem geneigten Hörer zum Selbststudium überlassen  Das war erst der Anfang... JNI bietet noch mehr: Erzeugen von Objekten, Aufruf von Konstruktoren Caching von Methoden-/Feld-Ids Exception-Handling … Diese Themen werden dem geneigten Hörer zum Selbststudium überlassen 

Fazit Enorme Möglichkeiten, positive Aspekte von C, C++ und Java zu integrieren Aufwand allerdings nicht unerheblich, daher sollten immer auch Alternativen in Betracht gezogen werden Für Standardaufgaben ist Einsatz von JNI aufgrund des stetig abnehmenden Performanz-Vorsprungs von C/C++ (wahrscheinlich) nicht lohnend