Upload
federicopaparoni
View
4.817
Download
1
Embed Size (px)
DESCRIPTION
java applicazioni native
Citation preview
J2EE Training: http://courses.coreservlets.com/Servlets, JSP, Struts, JSF, Hibernate, AJAX, Java 5, etc.
Developed and taught by well-known author and developer. At public venues or onsite at your location.
© 2006 Marty Hall
Invocare Applicazioni Native in Java
Slides Originali e codice d’esempio:http://courses.coreservlets.com/Course-Materials/java5.html
Traduzione a cura di:http://www.javastaff.com
J2EE training: http://courses.coreservlets.com
Agenda
• Opzioni di integrazione• Eseguire applicazioni native• Invocare funzioni native
J2EE training: http://courses.coreservlets.com
Collegamento a programmi in altri Linguaggi
• Invocare i programmi al livello OS– Usare ProcessBuilder per invocare un programma scelto a caso,
passando argomenti presi dallo standard input, e leggere i risultati dallo standard output
• Pro: facile da utilizzare, puo’ invocare qualsiasi applicazione.• Contro: numero limitato di argomenti da passare, lento:
overhead all’avvio considerevole.• Utilizzare le socket
– Utilizzare le socket per scambiare dati• Pro: veloce in locale, possibilità di distribuire le componenti su
piu’ macchine• Contro: set up laborioso, necessità di un protocollo di
comunicazione e di un parsing dei dati• Utilizzare metodi nativi
– Utilizzare JNI per linkare codice C e Java• Pro: veloce: utilizzabile per interazioni che richiedono particolare
cura.• Contro: metodo molto laborioso, necessita conoscenze di C, C+
+ o assebly
J2EE training: http://courses.coreservlets.com
Invocazione di applicazioni Native
1. Creare un ProcessBuilder– ProcessBuilder builder =
new ProcessBuilder("program", "argument");– Notare che le variabili di sistema non sono automaticamente
settate (il PATH ad esempio), quindi va utilizzato il path completo.
2. Lanciare il processo– builder.start();
Opzioni– Attendere che il processo termini (bloccante)
• Process p = builder.start();• int returnCode = p.waitFor();
– Esaminare i valori di ritorno successivamente (non bloccante)• int returnCode = p.exitCode();
J2EE training: http://courses.coreservlets.com
Esempio: Lanciare Internet Explorer
• Path completo di Internet Explorer:– C:\Programmi\Internet Explorer\iexplore.exe
• In Java bisogna utilizzare \\ per indicare \ • L’estensione .exe puo’ essere omessa in Windows
• Internet Explorer accetta parametri da riga di comando– URL iniziale da mostrare
• Sovrascrive l’homepage
J2EE training: http://courses.coreservlets.com
Esempio: Codice
public class InvokeIE { public static void main(String[] args) { String url = "http://www.javastaff.com/"; if (args.length > 0) { url = args[0]; } try { ProcessBuilder builder = new ProcessBuilder( "C:\\Programmi\\Internet Explorer\\iexplore", url); builder.start(); } catch(Exception e) { System.out.println(e); } }}
J2EE training: http://courses.coreservlets.com
Esempio: risultati
DOS> java InvokeIE http://www.javastaff.com/
J2EE training: http://courses.coreservlets.com
Leggere i risultati di un’applicazione nativa
1. Istanziare un ProcessBuilder– ProcessBuilder builder =
new ProcessBuilder("program", "argument");2. Avviare il processo
– Process p = builder.start();3. Utilizzare un Reader (come input, non
come output!)– BufferedReader reader =
new BufferedReader (new InputStreamReader (p.getInputStream()));
4. Leggere i risultati– Chiamare reader.readLine() finchè il risultato non è null
5. Chiudere lo stream– reader.close();
J2EE training: http://courses.coreservlets.com
Esempio: Invocare il comando Unix “ls”
import java.io.*;
public class InvokeLS { public static void main(String[] args) { String flags = "-al"; if (args.length > 0) { flags = args[0]; } try { ProcessBuilder builder = new ProcessBuilder("/usr/bin/ls", flags); Process process = builder.start();
J2EE training: http://courses.coreservlets.com
Esempio: Invocare il comando Unix “ls”
BufferedReader reader = new BufferedReader (new InputStreamReader (process.getInputStream())); String line; while((line = reader.readLine()) != null) { System.out.printf("Output: %s%n", line); } reader.close(); int status = process.exitValue(); if (status != 0) { System.out.printf("Error: process exited with %d.%n", status); } } catch(Exception e) { System.out.println(e); } }}
J2EE training: http://courses.coreservlets.com
Esempio: Invocare il comando Unix “ls” (Risultati indentati)Unix> java InvokeLSOutput: total 12Output: drwxr-xr-x 2 hall instruct 512 Nov 26 10:00 .Output: drwxr-xr-x 6 hall instruct 2048 Nov 26 09:38 ..Output: -rw-r--r-- 1 hall instruct 1257 Nov 26 10:00 InvokeLS.classOutput: -rw-r--r-- 1 hall instruct 846 Nov 26 10:00 InvokeLS.java
J2EE training: http://courses.coreservlets.com
Invocare Metodi Nativi
• E’ possibile chiamare funzioni C da Java– Le funzioni C++ devono essere dichiarate come "extern C"– Non si possono chiamare ad esempio funzioni FORTRAN, ma
funzioni C possono facilmente (?) fungere da intermediari• Vedi http://www.csharp.com/javacfort.html
• Si puo’ anche invocare funzioni Java da applicazioni C
• Molto piu’ laborioso– Necessita noiosa programmazione a basso livello su entrambe le
parti (Java e C)• Molto piu’ potente
– Si possono passare tipi di dati reali (non solo stringhe)– Non si lancia un processo per il Sistema Operativo ad ogni chiamata
• Maggiori dettagli– Generale: http://java.sun.com/docs/books/tutorial/native1.1/– MATLAB:
http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_external/f44062.html
J2EE training: http://courses.coreservlets.com
Utilizzare Metodi Nativi
1. Creare classi Java con metodi nativi– Metodi stub dichiarati native– Caricare le librerie shared utilizzando System.loadLibrary
2. Compilare il codice Java – Utilizzare normalmente javac
3. Creare un header per la classe Java– Usando "javah -jni ClassName"
4. Scrivere un programma C con le funzioni progettate– includere ClassName.h and jni.h
5. Compilare l’applicazione C come shared library– Includere come path must javahome/include e javahome/include/operatingsystem
6. Lanciare il programma Java– Utilizzando normalmente java
J2EE training: http://courses.coreservlets.com
Creare Classi Java
• Bisogna usare la dichiarazione native• Must caricare le librerie shared prima di
invocarne i metodi
public class HelloWorld { static { System.loadLibrary("hello"); }
public native void displayHelloWorld();
public static void main(String[] args) { new HelloWorld().displayHelloWorld(); }}
J2EE training: http://courses.coreservlets.com
Creare un File Header
> javac HelloWorld.java> javah -jni HelloWorld
– Result: HelloWorld.h/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloWorld */
#ifndef _Included_HelloWorld#define _Included_HelloWorld#ifdef __cplusplusextern "C" {#endif...JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);...
J2EE training: http://courses.coreservlets.com
Scrivere il programma C
#include <jni.h>#include "HelloWorld.h"#include <stdio.h>
JNIEXPORT void JNICALLJava_HelloWorld_displayHelloWorld (JNIEnv *env, jobject obj){ printf("Hello world!\n"); return;}
J2EE training: http://courses.coreservlets.com
Compilare il programma C come libreria Shared
• Bisogna includere i file .h files per JNI– Generali– Specifici del OS utilizzato
Solaris> gcc -I/usr/java1.5/include -I/usr/java1.5/include/solaris
HelloWorldImp.c -o libhello.so
J2EE training: http://courses.coreservlets.com
Invocare il programma Java
Solaris> java HelloWorldHello world!
J2EE training: http://courses.coreservlets.com
Mappatura dei tipi Java in tipi C (Primitive)
Java Type Native Type Size in Bits
boolean jboolean 8, unsigned
byte jbyte 8
char jchar 16, unsigned
short jshort 16
int jint 32
long jlong 64
float jfloat 32
double jdouble 64
void void
J2EE training: http://courses.coreservlets.com
Mappatura di Oggetti Java in C
• Tutte le chiamate sono fatte per riferimento• Tutti gli oggetti sono jobject in C• Alcuni sottotipi di jobject predefiniti
– jstring– jintArray, jshortArray, jlongArray– jfloatArray, jdoubleArray– jcharArray– jbyteArray– jbooleanArray– jobjectArray
J2EE training: http://courses.coreservlets.com
Chiamare Metodi Java da C
• Chiamare la funzione GetObjectClass • Chiamare GetMethodID• Chiamare CallVoidMethod
JNIEXPORT void JNICALL Java_Callbacks_nativeMethod(JNIEnv *env, jobject obj, jint depth) { jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); if (mid == 0) { return; } printf("In C, depth = %d, about to enter Java\n", depth); (*env)->CallVoidMethod(env, obj, mid, depth); printf("In C, depth = %d, back from Java\n", depth); }
J2EE training: http://courses.coreservlets.com
Ricapitolando
• Invocare applicazioni del sistema operativo– Utilizzare ProcessBuilder.start() per lanciare il
programma con i parametri opzionali– E’ possibile leggere l’output
• Utilizzando un BufferedReader sull’input stream• Si possono utilizzare le socket per la
comunicazione– Vedere la letteratura precedente– Molto veloce se entrambe le applicazioni sono sulla
stessa macchina• JNI offre l’integrazione piu’ elegante e
performante– Implementazione noiosa e molto a basso livello.
Manutenzione impegnativa.
J2EE Training: http://courses.coreservlets.com/Servlets, JSP, Struts, JSF, Hibernate, AJAX, Java 5, etc.
Developed and taught by well-known author and developer. At public venues or onsite at your location.
© 2006 Marty Hall
Domande?Visitate il forum di
http://www.javastaff.comse avete dubbi.