Portal > Foren > Ankündigungen, News und Feedback > Tutorials > [Java] Das Java Native Interface - Ein Einstieg
Antwort
 
LinkBack Themen-Optionen Thema durchsuchen
Alt 13.06.2009, 13:48 Nach oben    #1
fka Gottzilla
 
Benutzerbild von The_S
 
Registriert seit: 02.02.2005
Ort: Würzburg
Beiträge: 754
Standard [Java] Das Java Native Interface - Ein Einstieg

Das Java Native Interface - Ein Einstieg

Java ist eine plattformunabhängige Programmiersprache, weshalb du in ihr nicht system- und/oder hardwarenah programmieren kannst. Dennoch ist es manchmal hilfreich, einen Zugriff auf die Systemressourcen zu erhalten. Z. B. wenn du ein plattformabhängiges Programm in Kauf nehmen kannst, aber Java dir mehr als alle anderen (nativen) Sprachen liegt. Oder wenn das Programm prinzipiell plattformunabhängig gestaltet werden soll, aber nur kleine, native Funktionen benötigt werden. In diesem Fall ist es einfacher das komplette Programm in Java zu schreiben und lediglich den plattformabhängigen Code in native Programmbibliotheken auszulagern.

Um so etwas zu realisieren, benötigst du eine entsprechende native Schnittstelle zu deinem Java-Programm. Diese kannst du z. B. über JNI (Java Native Interface) oder JNA (Java Native Access) realisieren. Der Unterschied zwischen den beiden Bibliotheken liegt darin, dass du mit JNA auf bestehende Bibliotheken zugreifen kannst. Mit JNI programmierst du bspw. in C oder C++ eine eigene Bibliothek, und greifst dann von deinem Java-Programm auf diese zu. Umgekehrt kannst du natürlich auch aus deiner nativen Bibliothek auf Java-Methoden zugreifen oder sogar eine komplette JVM ausführen (Invocation-API).

Da JNI deutlich umfangreicher, unbeschränkter und flexibler als JNA ist, beschäftigt sich dieses Tutorial größtenteils mit JNI. Für dieses Tutorial und um mit JNI arbeiten zu können, benötigst du zusätzlich eine entsprechende Entwicklungsumgebung für native Programme (hier eine C/C++-Umgebung wie z. B. gcc) und das Programm javah aus dem bin-Verzeichnis deines JDKs. Da JNI mit dem JDK 1.1 eingeführt wurde, musst du dir keine Gedanken machen, dass du eine zu alte Java-Version verwendest. Vorher gab es das NMI (Native Methode Interface).

Nachdem du nun weißt, was JNI ist und für was du es alles einsetzen kannst, programmierst du heute ein erstes HelloWorld-Programm mit JNI. Dabei rufst dein Java-Programm eine selbst geschriebene C-Bibliothek auf, welche ein einfaches Hello World auf der Konsole ausgibt.

Installation einer C/C++ Umgebung
Damit du aus deinem C/C++-Code eine Programmbibliothek (z. B. unter Windows *.dll oder bei Solaris *.so) erstellen kannst, benötigst du zuerst eine entsprechende Umgebung (ähnlich dem JDK). Hierfür bietet sich gcc an. Für die Windows-Plattform kannst du auf Cygwin oder MinGW zurückgreifen. Bei der Installation musst du lediglich darauf achten, dass du gcc-core, gcc-g++, gdb und make mit installierst.
Nachdem die Installation erfolgreich abgeschlossen wurde, solltest du noch das bin-Verzeichnis, welches den gcc enthält, in die Umgebungsvariable PATH mit aufnehmen.
Natürlich kannst du auch eine andere Umgebung zur Entwicklung Ihrer nativen Schnittstellen verwenden. Dieses Tutorial bezieht sich allerdings auf den gcc.
Wenn du alles richtig gemacht hast, kannst du jetzt über deine Konsole folgendes Kommando ohne Fehlermeldung ausführen:
Code:
gcc --version


Das Java-Programm

Erstelle eine neue Klasse mit dem Namen HelloJNIWorld und dem Inhalt
java Code:
  1. package de.jbb.jni;
  2.  
  3. public class HelloJNIWorld {
  4.  
  5.   static {
  6.     System.loadLibrary("helloworld");
  7.   }
  8.  
  9.   public static void main(String[] args) {
  10.     printHelloWorld();
  11.   }
  12.  
  13.   public static native void printHelloWorld();
  14. }

im Package de.jbb.jni. Wie du auch in dem Kapitel über weitere Modifizierer lesen kannst, verweist die Methode printHelloWorld dank des native-Modifizierers auf eine native Implementierung dieser Methode. Der statische Initialisierer sorgt dafür, dass die native Bibliothek beim Start geladen wird. Hierzu wird die Methode loadLibrary der Klasse System verwendet. Wir gehen davon aus, dass sich die Library im selben Verzeichnis wie das Programm befindet (oder zumindest im library.path), weshalb es genügt, den Namen der Bibliothek ohne Dateiendung zu nennen (die Dateiendung wird - je nach Plattform - automatisch hinzugefügt).
Der library.path ist der Ort, an dem Java nach Bibliotheken sucht. Du kannst dir diesen Pfad über System.out.println(System.getPropertie("java.libra ry.path")); anzeigen lassen.
Es ist ebenfalls möglich zum Laden der Bibliothek einen absoluten Pfad, wie z.B. C:\java\dlls\helloworld.dll zu verwenden. Diesen lädst du dann aber nicht über System.loadLibrary sondern über System.load.

Die Klasse kann nun ganz normal kompiliert werden.

Die Header-Datei
So wie Java-Programme imports von Klassen zur Funktionserweiterung benötigen, benötigen C-Programme includes von Header-Dateien.
Eine Header-Datei enthält unter aanderem Deklarationen für den eigentlichen Quellcode und bilden in einer gewissen Form die Schnittstellen zwischen den unterschiedlichen Programmelementen.
Damit du eine Schnittstelle zwischen Java und C/C++ aufbauen kannst, wird zwingend eine solche Header-Datei benötigt. Um diese Datei zu erstellen, bietet Java das Tool javah an. Hiermit lassen sich automatisiert solche Header-Dateien für eine Klasse mit einem nativen Aufruf erzeugen. Dieses Programm findest du im bin-Verzeichnis deiner JDK-Installation. Da sich dieses Verzeichnis ohnehin in der PATH-Variable befinden sollte, kannst du das Tool ohne Probleme von überall aus auf der Konsole starten. Der Aufruf schaut genauso wie ein normaler java-Aufruf aus - nur eben mit javah anstelle von java:

Code:
javah de.jbb.jni.HelloJNIWorld
Auf der selben Ebene wie dein de-Ordner befindet sich nun die Header-Datei mit dem Namen de_jbb_jni_HelloJNIWorld.h. Es ist wichtig, dass du diese Datei niemals veränderst oder anpasst, sie sollte dann in etwa so aussehen:

java Code:
  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class de_jbb_jni_HelloJNIWorld */
  4.  
  5. #ifndef _Included_de_jbb_jni_HelloJNIWorld
  6. #define _Included_de_jbb_jni_HelloJNIWorld
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10. /*
  11. * Class:     de_jbb_jni_HelloJNIWorld
  12. * Method:    printHelloWorld
  13. * Signature: ()V
  14. */
  15. JNIEXPORT void JNICALL Java_de_jbb_jni_HelloJNIWorld_printHelloWorld
  16. (JNIEnv *, jclass);
  17.  
  18. #ifdef __cplusplus
  19. }
  20. #endif
  21. #endif

Das C-Programm
Nun ist es an der Zeit die dazugehörige Library zu erstellen. Entweder verwendest du ein C/C++ Plugin für Ihre IDE (z. B. CDT für Eclipse), oder du legst von Hand eine neue Textdatei an, und benennen diese in helloworld.c um. Diese Datei öffnest du dann mit einem beliebigen Texteditor und fügst folgenden Code ein:

Code:
#include <jni.h>
#include <stdio.h>
#include "de_jbb_jni_HelloJNIWorld.h"

JNIEXPORT void JNICALL Java_de_jbb_jni_HelloJNIWorld_printHelloWorld(JNIEnv *env, jclass cls)   {
  printf("Hello World\n");
  return;
}
Beachte, dass eine Leerzeile am Ende der Datei stehen muss!
Wie du bereits weißt, entsprechen die include-Zeilen in etwa den import-Anweisungen aus Java. Es werden also folgende Header-Dateien importiert:
  • jni.h - für die Standard-JNI-Funktionen
  • stdio.h - für die Funktionen zur Ausgabe von Text auf der Konsole
  • de_jbb_jni_HelloJNIWorld.h - der eben generierte Header als Schnittstelle zu unserem Java-Programm
Jetzt folgt auch schon die Implementation Ihrer nativen Methode. Solche Methoden beginnen immer mit JNIEXPORT gefolgt vom Rückgabetyp (in unserem Fall void) und dem Macro JNICALL. Anschließend folgt der Name der Methode. Er beginnt immer mit Java, gefolgt vom Package der Klasse mit den nativen Methoden und letztendlich der Klasse selbst und dem Namen der nativen Methode. Die einzelnen Elemente sind dabei jeweils durch Unterstriche getrennt Java_de_jbb_jni_HelloJNIWorld_pintHelloWorld. Als Parameter werden der Methode standardmäßig die JNI-Umgebung (JNIEnv *env) und die aufrufende Klasse (jclass cls) bei statischen Methoden, bzw. das aufrufende Objekt (jobject obj) bei Objektmethoden übergeben. Sollte die Methode an sich noch Parameter erwarten, folgen diese im Anschluss.
Die Zeile printf("Hello World\n"); gibt erwartungsgemäß den Text “Hello World” aus und das abschließende return; beendet die Methode.


Kompilierung des C-Codes
Nun musst du deinen C-Quellcode noch in eine Bibliothek umwandeln. Wenn du - wie oben empfohlen - gcc verwendest, sieht der dazugehörige Aufruf im Verzeichnis deiner C-Datei auf der Konsole wie folgt aus:
Code:
gcc -mno-cygwin -I"pfad\zum\jdk\include\os" -I"pfad\zum\jdk\include" -I"pfad\zum\verzeichnis\von\de_jbb_jni_HelloJNIWorld" -Wl,--add-stdcall-alias -shared -o helloworld.sfx helloworld.c
Du musst jetzt noch die Pfade der -I-Aufrufe anpassen. Dabei werden folgende Verzeichnisse übergeben (relativ oder absolut):
  1. Den Pfad zum include-Ordner im Installationsverzeichnis deines JDKs
  2. Den Ordner im include-Ordner mit dem Namen deines Betriebssystems (z. B. win32 für Windows oder solaris für Solaris)
  3. Den Pfad zum Verzeichnis, wo sich deine erzeugte Header-Datei (de_jbb_jni_HelloJNIWorld.h) befindet
Die letzten beiden Parameter spezifizieren den Namen der Programmbibliothek (ändere hier bitte die Dateiendung .sfx in die Dateiendung der Programmbibliotheken Ihres Betriebssystems - z. B. .dll für Windows oder .so für Solaris ab) und der Source-Datei.

Nach Absenden dieses Befehls wird eine native Bibliothek im aktuellen Verzeichnis erstellt. Kopiere die erstellte Datei nun auf die selbe Ebene, in der sich auch der de-Ordner deines Java-Programms befindet (bzw. falls du load anstelle von loadLibrary verwendet hast, an die Stelle, die du angegeben hast).

Jetzt kannst du dein Java-Programm ganz normal ausführen und solltest die Konsolenausgabe Hello World erhalten.

Dieses Tutorial wird uns mit freundlicher Genehmigung von java-blog-buch.de zur Verfügung gestellt.
Solltest du Fragen zu diesem Tutorial haben, so schreibe bitte einen Beitrag im Java-Forum mit einem Verweis auf dieses Tutorial.

Geändert von Jann Hendrik (01.07.2009 um 15:54 Uhr)
The_S ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus


Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
[Java] Suche Java und Eclipse-Entwickler mepeisen Gesuche 0 14.02.2008 17:36
[JAVA] Wie man aus Java mit einem PHP-Script kommuniziert sparrow Tutorials 0 25.03.2006 22:24
Sourcecode von Klassen aus Java Native Interface (JNI) xyz Allgemeine Java-Programmierung 0 22.11.2005 10:21
[BUCH] Java ist auch eine Insel kampet Literatur 5 22.02.2005 14:40
Zwist um Java als Open Source kampet Nachrichten 0 05.07.2004 03:37


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:40 Uhr.


Powered by vBulletin® Version 3.8.4 (Deutsch)
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47