Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
1 Neues in Java 7
2 Threads und nebenläufige Programmierung
3 Datenstrukturen und Algorithmen
4 Raum und Zeit
5 Dateien, Verzeichnisse und Dateizugriffe
6 Datenströme
7 Die eXtensible Markup Language (XML)
8 Dateiformate
9 Grafische Oberflächen mit Swing
10 Grafikprogrammierung
11 Netzwerkprogrammierung
12 Verteilte Programmierung mit RMI
13 RESTful und SOAP Web-Services
14 JavaServer Pages und Servlets
15 Applets
16 Datenbankmanagement mit JDBC
17 Technologien für die Infrastruktur
18 Reflection und Annotationen
19 Dynamische Übersetzung und Skriptsprachen
20 Logging und Monitoring
21 Java Native Interface (JNI)
22 Sicherheitskonzepte
23 Dienstprogramme für die Java-Umgebung
Stichwort
Download: - openbook, ca. 21,3 MB
Buch bestellen
Ihre Meinung?
<< zurück | Galileo Computing / <openbook> / Java 7 - Mehr als eine Insel | vor >>
Java 7 - Mehr als eine Insel von Christian Ullenboom Das Handbuch zu den Java SE-Bibliotheken
Java 7 - Mehr als eine Insel Galileo Computing 1433 S., 2012, geb. 49,90 Euro, ISBN 978-3-8362-1507-7 |
| 21 Java Native Interface (JNI)
|  | 21.1 Java Native Interface und Invocation-API
|  | 21.2 Eine C-Funktion in ein Java-Programm einbinden
|  |  | 21.2.1 Den Java-Code schreiben
|  | 21.3 Dynamische Bibliotheken erzeugen
|  |  | 21.3.1 Die Header-Datei erzeugen
|  |  | 21.3.2 Implementierung der Funktion in C
|  |  | 21.3.3 Die C-Programme übersetzen und die dynamische Bibliothek überzeugen
|  | 21.4 Nativ die Stringlänge ermitteln
|  | 21.5 Erweiterte JNI-Eigenschaften
|  |  | 21.5.1 Klassendefinitionen
|  |  | 21.5.2 Zugriff auf Attribute
|  |  | 21.5.3 Methoden aufrufen
|  |  | 21.5.4 Threads und Synchronisation
|  | 21.6 Einfache Anbindung von existierenden Bibliotheken
|  |  | 21.6.1 Generieren von JNI-Wrappern aus C++-Klassen und C-Headern
|  |  | 21.6.2 COM-Schnittstellen anzapfen
|  | 21.7 Invocation-API
|  | 21.8 Zum Weiterlesen
## 21.3 Dynamische Bibliotheken erzeugen Im zweiten Schritt kann der Java-Code übersetzt werden, denn jetzt würde eine Ausführung einen Fehler produzieren. Existiert die dynamische Bibliothek nicht oder ist sie nicht im Pfad eingebunden, folgt ein Fehler wie der folgende:
    java.lang.UnsatisfiedLinkError: no strlen in java.library.path
      at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
      at java.lang.Runtime.loadLibrary0(Runtime.java:822)
      at java.lang.System.loadLibrary(System.java:992)
      at com.tutego.jni.StrLen.<clinit>(StrLen.java:7)
    Exception in thread "main"
Für die nativen Methoden auf der Java-Seite gibt es auf der C(++)-Seite entsprechende Implementierungen. Da die Implementierung noch nicht erstellt wurde, gibt es logischerweise einen Laufzeitfehler. ### 21.3.1 Die Header-Datei erzeugen Die nativ implementierten Funktionen verfügen über eine bestimmte Signatur, damit die JVM bei einem Aufruf aus der Java-Welt an die native Implementierung weiterleiten kann. Wie die Signatur aussieht, definiert die JNI-Spezifikation. Um es so einfach wie möglich zu machen, generiert ein Hilfsprogramm aus der Java-Klasse mit der nativen Methode eine C(++)-Header-Datei. Eine Header-Datei enthält Makros und Konstanten und definiert sowie dokumentiert oftmals die Funktionen, die dann später in der C(++)-Datei realisiert werden. (Ein bisschen entspricht das den Schnittstellen und den Klassen, die sie implementieren.) Die Header-Datei gibt die Signatur der Funktionen vor und wird nicht verändert. Anschließend inkludiert das C(++)-Programm die Header-Dateien und implementiert die vorgegebene Funktion. Dann kann das C(++)-Programm übersetzt, in eine dynamische Bibliothek eingepackt und von der JVM ausgelesen werden. Kommen wir zum ersten Schritt: Ein Generator erstellt die Header-Datei, der aus der Klassendatei die Methoden-Signatur und Rückgabe ausliest und nach einem festen Schema die Funktionen auf der C(++)-Seite benennt. Zum Aufruf des Generators bietet sich ein Ant-Skript an, und auch das JDK bringt mit javah ein Dienstprogramm mit. Mit Ant erstellt der Task <javah> die entsprechende Header-Datei: Listing 21.3: build.xml, Ausschnitt
    <javah classpath="bin" outputFile="strlen.h" verbose="yes">
      <class name="com.tutego.jni.StrLen" />
    </javah>
In diesem Beispiel soll für die Klasse StrLen die Header-Datei strlen.h generiert werden.
Hinweis
Soll das Kommandozeilenprogramm javah benutzt werden, so bestimmt der Schalter -o den Namen der Ausgabedatei: $ javah -jni -o strlen.h com.tutego.jni.StrLen Die volle Qualifizierung ist wichtig, andernfalls gibt es merkwürdige Fehler wie "error: cannot access StrLen" und "bad class".
An der entstandenen Header-Datei strlen.h sollten keine Änderungen vorgenommen werden. Werfen wir einen Blick hinein, damit wir wissen, welche C-Funktion wir implementieren müssen: Listing 21.4: strlen.h
    /* DO NOT EDIT THIS FILE – it is machine generated */
    #include <jni.h>
    /* Header for class com_tutego_jni_StrLen */

    #ifndef _Included_com_tutego_jni_StrLen
    #define _Included_com_tutego_jni_StrLen
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_tutego_jni_StrLen
     * Method:    strlen
     * Signature: (Ljava/lang/String;)I
     */
    JNIEXPORT jint JNICALL Java_com_tutego_jni_StrLen_strlen
      (JNIEnv *, jclass, jstring);

    #ifdef __cplusplus
    }
    #endif
    #endif
Die Funktion heißt auf der C-Seite nicht einfach strlen(), weil wegen fehlender Namensräume sonst Verwechslungsgefahren mit anderen nativen Methoden anderer Pakete nicht ausgeschlossen sind. Aus diesem Grund enthält der Funktionsname auf der C-Seite den Paketnamen und den Namen der Java-Klasse. Dementsprechend setzt sich der Funktionsname zusammen aus: einem Präfix Java, dem vollständigen Klassenbezeichner, wobei die einzelnen Glieder im Paket durch »_« und nicht durch ».« getrennt sind, und dem Namen der Methode. Alle primitiven Java-Typen sind auf spezielle Typen in C abgebildet. So steht jint für ein Integer und jstring für einen Pointer auf eine Zeichenkette. ### 21.3.2 Implementierung der Funktion in C In der automatisch erzeugten Header-Datei lässt sich die Signatur der Funktion ablesen; die Basis für die Implementierung ist:
    JNIEXPORT jint JNICALL Java_com_tutego_jni_StrLen_strlen(
                                        JNIEnv *, jclass, jstring );
Wir erzeugen eine neue Datei, strlen.c, mit einer Implementierung für Java_com_tutego_ jni_StrLen_strlen(). Dabei soll zunächst etwas auf dem Bildschirm ausgegeben werden; wir wollen damit testen, ob überhaupt alles zusammen läuft. Anschließend kümmern wir uns um die Zeichenkettenlänge. Listing 21.5: strlen.c
    #include <jni.h>
    #include "strlen.h"
    #include <stdio.h>
    JNIEXPORT jint JNICALL Java_com_tutego_jni_StrLen_strlen(
                                JNIEnv *env, jclass clazz, jstring s )
    {
      printf( "Hallo Java-Freunde!\n" );
      return 0;
    }
Der erste Parameter, env, zeigt auf die JNI-Umgebung, über die alle JNI-Funktionen zur Verfügung stehen. Wir werden sie später nutzen. ### 21.3.3 Die C-Programme übersetzen und die dynamische Bibliothek überzeugen Der C(++)-Compiler muss nun die dynamische Bibliothek übersetzen. Die dynamisch ladbaren Bibliotheken sind unter Windows die .dll-Dateien (dynamic link libraries ) und unter Unix Dateien mit der Endung .so (shared objects). Die .dll- und .so-Dateien erzeugt prinzipiell jeder Compiler, wobei zu beachten ist, dass jeder Compiler andere Aufrufkonventionen befolgt. Auf dem Markt gibt es eine Reihe guter und freier Compiler, die für die Übersetzung verwendet werden können: GCC (GNU Compiler Collection) http://gcc.gnu.org/; freier Klassiker für unzählige Plattformen Microsoft Visual C++ 2010 Express http://www.microsoft.com/germany/express/products/windows.aspx; Übersetzer für C(++)- und .NET-Programme C++ Compiler https://downloads.embarcadero.com/item/24778; der Compiler ist nur für Windows verfügbar. Embarcadero hat den Compiler von Borland übernommen. #### Die GNU Compiler Collection unter Cygwin Da jeder Compiler andere Aufrufkonventionen hat, führen wir unser Beispiel mit dem GNU Compiler durch. GCC ist klassischerweise ein Unix-Compiler, doch gibt es ihn auch für Windows. Cygwin portiert die unter Unix bekannten Tools für Windows, und ein Teil der Tool-Sammlung ist der C(++)-Compiler. Für die Installation wird zunächst unter http://www.cygwin.com/ das kleine Programm set-up.exe geladen und ausgeführt (es steckt hinter dem Link Install or update Cygwin now). Nach dem Start überspringe das Willkommensfenster mit Weiter >. Wähle den Eintrag Install from Internet aus, um aus dem Internet alle nötigen Pakete geladen zu bekommen. Wähle dann Weiter >. Gib bei Root Directory zum Beispiel c:\cygwin ein, und wähle Weiter >. Cygwin speichert die geladenen Teile erst zwischen und möchte dazu ein Verzeichnis bekommen – das Verzeichnis kann nach der Installation gelöscht werden. Vorgewählt ist der Desktop. Der Eintrag wird geändert oder so belassen. Dann Weiter >. Im Folgenden lassen sich Verbindungsdaten einstellen, damit das Setup-Programm die Programme aus dem Internet laden kann. Die Voreinstellung Direct Connection passt im Regelfall. Dann Weiter >. Wähle aus der Liste einen Server aus, von dem die Dateien geladen werden. Dann aktiviere Weiter >. Falls jetzt ein Setup Alert kommt, kann dieser mit OK geschlossen werden. Wähle aus dem Zweig Devel den Eintrag gcc-core (bzw. gcc-g++). (Den gdb können wir angeben, wenn C-Programme debuggt werden sollen.) Dann Weiter >. Die Wahl selektiert automatisch ein paar weitere abgeleitete Pakete und zeigt sie an. Dann Weiter >. Der tatsächliche Download beginnt. Es lassen sich Icons setzen. Sie sind nicht nötig und können abgewählt werden. Weiter > schließt die Installation ab. #### Übersetzen mit Ant Das Build-Tool Ant bringt in der Standard-Distribution keinen Task mit, der einen C-Compiler anstößt. Nichtsdestotrotz lassen sich mit <exec> externe Programme aufrufen. Somit sieht das ganze Build-Skript folgendermaßen aus: Listing 21.6: build.xml
    <project default="cc" basedir=".">

       <target name="javah">
          <javah classpath="bin" outputFile="strlen.h" verbose="yes">
             <class name="com.tutego.jni.StrLen" />
          </javah>
       </target>

       <target name="cc" depends="javah">

          <exec dir="c:\cygwin\bin\" executable="c:\cygwin\bin\gcc-3">
             <arg value="-mno-cygwin" />
             <arg value="-I" />
             <arg value="C:\Program Files\Java\jdk1.7.0\include" />
             <arg value="-I" />
             <arg value="C:\Program Files\Java\jdk1.7.0\include\win32" />
             <arg value="-shared" />
             <arg value="-Wl,--add-stdcall-alias" />
             <arg value="-o" />
             <arg value="${basedir}\strlen.dll" />
             <arg value="${basedir}\strlen.c" />
          </exec>

       </target>

    </project>
Hinweis
Die dynamische Bibliothek muss unter Windows die Endung .dll und unter Unix-Systemen die Endung .so haben. In der Unix-Welt beginnen die dynamischen Bibliotheken mit dem Präfix lib, sodass sich daraus für eine Datei die Namensgebung libName.so ergibt.
Wer den <exec>-Task nicht verwenden mag, der kann auch die externen CC-Tasks unter http://ant-contrib.sourceforge.net/ nutzen. ### Ihr Kommentar Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück | <top> | vor >>
Zum Katalog
Java 7 – Mehr als eine Insel Jetzt bestellen
Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen? Ihre Meinung
Buchempfehlungen
| Java und XML
| Einstieg in Eclipse 3.7
| Android 3
| NetBeans Platform 7
| Java ist auch eine Insel
| Apps entwickeln für Android 4
| Java 7
Shopping
Versandkostenfrei bestellen in Deutschland und Österreich Info

Copyright © Galileo Press 2012
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

[Galileo Computing]
Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de