Java Native Calls

Werbung
Java Native Calls
Einbinden von C Bibliotheken in Java Klassen
Prof. Dr. Nikolaus Wulff
MVC: VC-GUI und natives M
• Der FunctionPlotter wird in Java implementiert und
stellt die View und Controller Abstraktionen bereit.
• In Praktikum I wurden der numerische Integrator
und der Differentiator in C entwickelt. Deren
Kernfunktionalität kann als Model betrachtet
werden. Es gibt nun zwei Möglichkeiten:
• Entweder die C Implementierung in Java komplett
neu zu implementieren oder aber
• eine Java Wrapper Klasse als Adapter zu schreiben,
die an die fachliche C Implementierung delegiert.
© Prof. Dr. Nikolaus Wulff
Informatik III
2
Native Code
• Java bietet die Möglichkeit Klassen mit Methoden
zu schreiben, die in C realisiert werden.
• Hierzu werden die Methoden mit dem Schlüsselwort native markiert, ohne das eine Implementierung in Java erfolgt.
public class Differentiator {
/**
* Differentiate the given function.
* @param fct to differentiate
* @param x the function argument
* @return f'(x)
*/
public native double differentiate(
final Function fct, final double x);
}
© Prof. Dr. Nikolaus Wulff
Informatik III
3
C Header-Dateien generieren
• Mit dem Tool javah wird zu Differentiato.java ein
C Header PackageName_Differentiato.h generiert.
• Die Datei PackageName_Differentiator.c dient als
Adapter zu den schon existieren C Routinen.
de_lab4inf_Differentiator.h
de_lab4inf_Differentiator.c
javah
javap
differentiate.h
differentiate.c
differentiate.c
function.h
integrate.h
integrate.c
libCPrak-I.so
© Prof. Dr. Nikolaus Wulff
Informatik III
4
de_lab4inf_Differentiator.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class de_lab4inf_jni_Differentiator */
#ifndef _Included_de_lab4inf_Differentiator
#define _Included_de_lab4inf_Differentiator
#ifdef __cplusplus
extern "C" {
double differentiate(Function fct, double x)
#endif
/*
* Class:
de_lab4inf_Differentiator
* Method:
differentiate
* Signature: (Lde/lab4inf/Function;D)D
*/
JNIEXPORT jdouble JNICALL
Java_de_lab4inf_Differentiator_differentiate
(JNIEnv *, jobject, jobject, jdouble);
#ifdef __cplusplus
}
#endif
#endif
JVM
© Prof. Dr. Nikolaus Wulff
this Zeiger
Informatik III
Funktionsargumente
5
Differentiator.c howto?
• Wie kann jetzt die C Methode implementiert
werden (ohne das alte Pratkium neu zu schreiben)?
• Benötigt wird nicht nur der Wert x, sondern auch
ein C FunctionPointer für die zugehörige Java
Funktion, die nur als Schnittstelle definiert ist.
• Es lassen sich nicht nur von Java aus C Routinen
rufen, sondern diese können auch ihrerseits wieder
auf Java Klassen, Objekten und alle Methoden
zurückgreifen!
© Prof. Dr. Nikolaus Wulff
Informatik III
6
Einbinden der C Routinen
• Der Integrator und der Differentiator wurden im
ersten Praktikum in C realisiert.
• Es werden nun zwei Java Klassen Integrator und
Differentiator als Adapter geschrieben, diese sollen
jedoch nicht komplett neu implementiert werden,
sondern statt dessen die C Routinen aufrufen.
• Dies geschieht mit Hilfe der Java Native Interface
Schnittstelle JNI.
• Es werden C Header Dateien generiert, die nur noch
geeignet ausimplementiert werden müssen.
• Es werden entsprechende C Methoden als „Glue“
zu den Routinen aus Praktikum I entwickelt.
© Prof. Dr. Nikolaus Wulff
Informatik III
7
Java Reflection
• Jedem Java Objekt ist eineindeutig ein Class Objekt
zugeordnet.
– Class c = obj.getClass()
• Dieses Class Objekt enthält Metainformationen und
bietet „Java FunctionPointer“:
– Method m = c.getDeclaredMethod(name, ...)
– Field f = c.getDeclaredField(name)
• Diese „FunctionPointer“ erlauben das Objekt zu
manipulieren:
– double x = f.getDouble(obj)
– m.invoke(obj, ...)
© Prof. Dr. Nikolaus Wulff
Informatik III
8
Shapes kanonische Form
• Die Aufteilung in Methoden und Attribute erfolgt in
zwei Structs XXX_Instance und XXX_Class:
typedef struct Shape_Instance_struct* Shape;
typedef struct Shape_Class_struct {
void (*draw)
(Shape aShape);
void (*erase) (Shape aShape);
void (*moveTo) (Shape aShape, int x ,int y);
} ShapeClass;
typedef struct Shape_Instance_struct {
ShapeClass *class;
int pos_X;
int pos_Y;
<<Data>>
ShapeInstance
} ShapInstance;
ShapeClass
pos_X
pos_Y
© Prof. Dr. Nikolaus Wulff
Informatik III
<<Methods>>
ShapeClass
1
moveTo()
moveBy()
9
Java Reflection API
Class
Object
Package
1
name :
MyClass
myAttribute
<<Interface>>
Member
myMethod()
Constructor
(from
© Prof. Dr. Nikolaus Wulff
Field
(from
Informatik III
Method
(from
10
Native Code API
• Alle C Methoden erhalten eine Referenz auf die
JVM Umgebung und das entsprechende Java
Objekt, dessen native Methode entwickelt wird.
• Dieses „Umgebungsobjekt“ ist eine C Struktur, die
verschieden FunctionPointer anbietet, um Methoden und Felder beliebiger Objekt zu addressieren.
• Ermitteln des Class Objekts von obj
jclass clazz = (*env)->GetObjectClass(env, obj);
• Ermitteln der Methode „double getValue()“ :
Signatur
jmethodID method =
(*env)->GetMethodID(env, clazz, "getValue", "()D");
© Prof. Dr. Nikolaus Wulff
Informatik III
11
Zugriff auf Felder
• Felder können direkt aus C addressiert werden.
• Es wird keine Rücksicht auf private genommen!
jfieldID field;
field = (*env)->GetFieldID(env, clazz, "x", "D");
(*env)->SetDoubleField(env, obj, field, 1.0);
• Die zu verwendenen C Methoden sind in der Datei
<jni.h> deklariert.
© Prof. Dr. Nikolaus Wulff
Informatik III
12
Aufruf von Funktionen
• Aufruf der Methode „getValue“:
double x;
x = (*env)->CallDoubleMethod(env, obj, method);
• Gegenstück „setValue“:
Signatur
method = (*env)->GetMethodID(env, clazz, "setValue", "(D)V");
(*env)->CallVoidMethod(env, obj, method, x);
• Die Signatur dient dazu überladene Methoden
eindeutig zu identifizieren.
• Wie kann effizient die genaue Signatur der
Methode ermittelt werden?
© Prof. Dr. Nikolaus Wulff
Informatik III
13
Java Disassembler
• Der Java Disassembler javap gestattet es in das
Innere von Java Klassen zu schauen.
• Mit den Parametern -p -s liefert javap die Signatur
Informationen:
~/workspace/CPrak-III-1$ javap -s -p de.lab4inf.Differentiator
Compiled from "Differentiator.java"
public class de.lab4inf.Differentiator extends java.lang.Object{
public de.lab4inf.Differentiator();
Signature: ()V
public native double differentiate(de.lab4inf.Function, double);
Signature: (Lde/lab4inf/Function;D)D
static {};
Signature: ()V
}
© Prof. Dr. Nikolaus Wulff
Informatik III
14
Objekterzeugung
• Primitive Datentypen können dirket zurückgegeben
werden. Objekte müssen erst erzeugt werden:
jclass clazz;
jmethodID ctor;
jobject complex;
clazz = (*env)->FindClass(env, "math/Complex");
assert(clazz != NULL);
Konstruktor
Signatur
ctor = (*env)->GetMethodID(env, clazz, "<init>", "()V");
assert(ctor != NULL);
complex = (*env)->NewObject(env, clazz, ctor);
assert(complex != NULL);
return complex;
© Prof. Dr. Nikolaus Wulff
Informatik III
15
Einbinden der C Bibliothek
• Vor dem Verwenden von native Klassen muß die
zugehörige C Bibliothek geladen werden.
• Diese hat immer den generischen Namen
– libXXX.so für Unixe
– libXXX.dll für Windows
• Geladen wird sie am Besten beim Start der
Anwendung mit dem Aufruf:
– System.loadLibrary("XXX");
• gesucht wird dann im java.library.path. Oder mit
expliziter Pfadangabe (Achtung nicht portabel!):
– System.load("/pfad/libXXX.so");
© Prof. Dr. Nikolaus Wulff
Informatik III
16
Warnungen
• Mit dem C Code ist es möglich auf jedes Feld und
jede Methode der JVM zuzugreifen.
• Sogar eigene Semaphore, Mutexe und critical
Sections können geschrieben werden.
• Es ist möglich die gesamte JVM lahmzulegen.
• Es ist daher Vorsicht angebracht.
• Am Besten keine eigenen
Synchronisationsmechanismen in C!
• Kein malloc und free etc.
• Keine globalen Referenzen auf Objekte!
• Objekte mit Java Mitteln erzeugen, damit der
Garbage Collector den Speicher verwaltet.
© Prof. Dr. Nikolaus Wulff
Informatik III
17
Java und C ein gutes Gespann
• Mit Hilfe der Java Native API bleiben keine
Wünsche mehr offen.
• Ein guter Programmierer kann bis auf Betriebssystemebene gehen, sogar Assembler ist möglich.
• Die Eclipse ist ein gutes Beispiel für Java und C.
• Eclipse verwendet weder AWT noch Swing für die
GUI sondern das selbstentwickelte SWT.
• SWT ist eine Bibliothek, die aus graphischen
Klassen besteht, die vollkommen in C
implementiert sind und direkt delegieren an die
Widgets des jeweiligen Betriebsystems.
© Prof. Dr. Nikolaus Wulff
Informatik III
18
Herunterladen