FAKULTET INFORMACIONIH TEHNOLOGIJA Beograd, 2010 Integrativno programiranje softvera napisanog u 2 jezika, Java i C++ (Integrating programing, Java/C++ integration, Java/C++ Interface ) Predmet: SE411 Profesor: prof. dr. Slobodan Jovanović Student: Vladimir Bokun Br. indeksa: 1151
40
Embed
SE411-Seminarski 1-Integrativno programiranje softvera napisanog u 2 jezika, Java i c++
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
FAKULTET INFORMACIONIH TEHNOLOGIJA
Beograd, 2010
Integrativno programiranje softvera napisanog u 2 jezika, Java i C++ (Integrating programing, Java/C++ integration,
Java/C++ Interface )
Predmet: SE411
Profesor: prof. dr. Slobodan Jovanović
Student: Vladimir Bokun
Br. indeksa: 1151
[SE411-INTEGRATIVNO PROGRAMIRANJE U DVA PROGRAMSKA JEZIKA C++/JAVA]
4. Sugestije za nastavak rada ............................................................................................................ 39
5. Literatura ....................................................................................................................................... 40
[SE411-INTEGRATIVNO PROGRAMIRANJE U DVA PROGRAMSKA JEZIKA C++/JAVA]
December 16, 2010
4 | S t r a n a
REZIME
Java okruženje i jezik je siguran i efikasan način za razvoj aplikacija. Pa ipak, ponekad je za
aplikaciju potrebna odreĎena funkcionalnost, koju Java, zbog svoje težnje da bude
multiplatfomska, nije moguce postići, ili bar ne upotrebom same Jave.
Primjer za to su:
integracija sa postojećim bibliotekama direktno vezanim za funkcionalnosti nekog
operativnog sistema, ili hardvera
integracija sa kodom koji je najčešće napisan u C/C++, za postizanje većih performansi, ili
bolje iskorištenje sistema
Zbog toga je razvijen standard, JNI-Java Native Interface. O njemu će biti riječi u prvom dijelu
rada, načinu na koji funkcioniše, mapiranjima izmedju C/C++ i Java tipova podataka, kao i
problemima koji nastaju upotrebom ovog API-ja.
Sem JNI, biće predstavljeni i
KNI-K Native Inteface, namjenjen ureĎajima sa ograničenim hardverskim mogućnostima,
koji predstavlja podskup JNI,
CNI-Compiled Native Interface, gdje se Java posmatra kao podskup C++,
SWIG- Simplified Wrapper and Interface generator, interfejs kompajler koji povezuje
programe napisane u C i C++, sa skriptnim jezicima (Lua, Perl, Python, Ruby, Tcl) ali i
drugim, kao što je Java
JNA- Java native access, koji omogućava Java programima lak i brz pristup native
bibliotekama, bez upotrebe JNI interfejsa.
Ponekad je potrebno samo pokrenuti neki utility program, ili drugi u okviru Java programa. Tada je
moguće koristiti Runtime.exec komandu pa će i ona biti predstavljena.
U drugom dijelu rada, biće predstavljen primjer upotrebe JNI kroz JniExample Java projekat, i C++
projekat JniExampleLibrary, odnosno pozivanje Java metoda iz C++ biblioteke, i obrnuto,
pozivanje C++ metoda iz Java projekta. Okruženja korištena za izradu ova dva projekta su
Eclipse i Visual Studio 2010.
Sem izrade, naglasak je i na debug-u projekata, a posebna pažnja posvećena je i problemima koji
mogu nastati upotrebom ovog API-ja, tj. pucanja Java virtuelne mašine izazvanim loše
napisanim C++ kodom.
Uz ovaj rad priloženi su:
JniExample, Java projekat, uraĎen u Eclipse-u Helios (JniExample.rar)
JniExampleLibrary, C++ Win 32 projekat, uraĎen u Visual Studiju 2010
(JniExampleLibrary.rar)
[SE411-INTEGRATIVNO PROGRAMIRANJE U DVA PROGRAMSKA JEZIKA C++/JAVA]
December 16, 2010
5 | S t r a n a
UVOD
Često se javlja potreba da iz Java virtuelne mašine treba da pristupimo nekoj native1 metodi, npr.
grafičkim funkcijama niskog nivoa, pristupu fajlovima, funkcijama mreže, i drugim rutinama, koje
zavise od operativnog sistema u kome su implementirane, ili čak niže, na nivou harvera.
Ovakve metode su napisane u native kodu, koji se kompajliranjem prevodi na mašinski jezik
razumljiv hardveru. Način na koji će ove metode biti dostupne JVM može da varira, zavisno i od
načina na koji je sama JVM implementirana. Sa ciljem da se minimizuje rad potreban za
portabilnost ovakvog koda, uspostavljen je standard JNI (Java Native Interfaces).
Namjena JNI standarda je da:
posluži kao standardizovan interfejs ka virtualnoj mašini, tako da će iste native metode
jednako raditi pod različitim mašinama
obezbjedi na nivou Jave univerzalni API za dinamičko učitavanje biblioteka napisanih u
native kodu i pozivanju njihovih metoda
Naravno, ovo nije jedini način da se iz Java programa pozivaju native metode, napisane u native
programima, i zavisno od tipa interakcije izmedju njih, na raspolaganju je još nekoliko API-ja.
MeĎutim, sem pozitivnih strana ovakve interakcije, ne treba zaboraviti da:
loše napisan native kod može da obori čitavu JVM
zbog univerzalnosti implementacije API-ja, gubi se na brzini izvršavanja, kao i korišćenja
veće količine memorijskih resursa
dinamičko učitavanje i pozivanje native metoda iz Java programa može stvoriti sigurnosne
probleme, obzirom na nedostatak Java 2 security modela
Cilj integracije je iskorišćenje mogućnosti oba programska jezika, zavisno od potreba napisanog
Java programa, uz voĎenje računa o problemima koji mogu nastati pri ovakvoj implementaciji.
1 Native- metoda napisana u programu koji radi direktno sa hardverom, ili sa operativnim sistemom, na
niskom nivou.
[SE411-INTEGRATIVNO PROGRAMIRANJE U DVA PROGRAMSKA JEZIKA C++/JAVA]
December 16, 2010
6 | S t r a n a
1. INTEGRATIVNO PROGRAMIRANJE JAVA/C++
Java je razvijena sa ciljem da omogući nezavisnost od platformi na kojima se izvršava JVM.
MeĎutim često se nalazimo u situaciji da ne možemo iznova pisati aplikaciju, već želimo da
komuniciramo sa već napisanim softverom, koji je nižeg nivoa apstrakcije od Jave (legacy
softver, operativni sistemi).
Na ovaj način se nalazimo u problemu, jer ne možemo koristiti funkcije zavisne od sistema na kom
se izvršava JVM.
Prvo moguće rješenje je pozivanjem native metoda u samom Java kodu, pri čemu gubimo na
portabilnosti napisanog softvera. MeĎutim, ukoliko želimo da komuniciramo sa native
programima na jednostavnijem nivou, gdje želimo samo pokrenuti neki utility program, ili drugu
aplikaciju, na scenu stupa Runtime klasa, odnosno njena exec metoda.
JNI-Java Native Interface je postavljen kao standard za integraciju ova dva jezika, meĎutim na
raspolaganju nam je još nekoliko API-ja, a koji ćemo izabrati, zavisi od namjene samog
programa. To su, redom:
Runtime.Exec
JNI
KNI
CNI
SWIG
JNA
Uz nabrojane, postoje i komercijalni API-ji, npr.
JNIEasy
Jnative
JACE
Dalje ćemo predstaviti svaki od ovih API-ja, sem komercijalnih.
[SE411-INTEGRATIVNO PROGRAMIRANJE U DVA PROGRAMSKA JEZIKA C++/JAVA]
December 16, 2010
7 | S t r a n a
1.1. RUNTIME.EXEC
Runtime.exec je jednostavan interfejs, ka platformski zavisnim utility programima i aplikacijama. U
najprostijoj formi, primejer poziva Unix ls komande bi bio:
Process p = Runtime.getRuntime().exec("/bin/ls");
Za razliku od fork metode C-a, ne dozvoljava nam da direktno kontrolišemo okruženje. Novi proces
vrši redirekciju STDIN, STDOUT, STDERROR, pa rezultat poziva ne dobijamo na ekranu.
Umjesto toga, moramo koristiti getInputStream(), getOutputStream() i
getErrorStream()metode procesa, da bismo komunicirali sa pozvanim programom.
U listingu je dat primjer poziva komande ls:
Import java.io.*;
class execInput {
public static void main(String Argv[]) {
try {
String ls_str;
Process ls_proc = Runtime.getRuntime().exec("/bin/ls -aFl");
// get its output (your input) stream
BufferedReader br_in= new BufferedReader(new
InputStreamReader(ls_proc.getInputStream()));
try {
while ((ls_str = br_in.readLine()) != null) {
System.out.println(ls_str);
}
} catch (IOException e) {
System.exit(0);
}
} catch (IOException e1) {
System.err.println(e1);
System.exit(1);
}
System.exit(0);
}
}
Od verzije JDK 1.1 PATH varijabla je poznata, ali je i pored toga dobra praksa proslijeĎivati punu
putanju do programa koga pokrećemo.
Shell ugradjene komande operativnog sistema neće raditi u svim slučajevima, bar ne na
jednostavan način koa što smo navikli. Npr. za poziv DOS dir komande, poziv bi bio
command \c dir
Ukoliko želimo da proslijedimo više parametara za redom, umjesto pisanja komande u stringu i
proslijeĎivanja exec metodi, potrebno je napraviti komandu kao niz stringova, i takav niz predati
za argument.
Postoje četiri overloaded exec metode klase Proces, redom:
[SE411-INTEGRATIVNO PROGRAMIRANJE U DVA PROGRAMSKA JEZIKA C++/JAVA]
December 16, 2010
8 | S t r a n a
public Process exec(String command); public Process exec(String [] cmdArray); public Process exec(String command, String [] envp); public Process exec(String [] cmdArray, String [] envp);
Trošak upotrebe ove komande je što gubimo na portabilnosti napisanog Java softvera, dok je sa
druge strane najjednostavniji način da koristimo, i pokrećemo alate i utility-je operativnog
sistema, ali i druge programe. Česta primjena kod Java programera je upotreba ove komande
za pozivanje eksterno napisanih Help stranica (.chm i sl.) za aplikacije iz kojih se pokreću.
[SE411-INTEGRATIVNO PROGRAMIRANJE U DVA PROGRAMSKA JEZIKA C++/JAVA]
December 16, 2010
9 | S t r a n a
1.2. JNI-JAVA NATIVE INTERFACE
JNI je univerzalni interfejs koji dozvoljava Java kodu u okviru JVM da poziva, i bude pozivan od
strane native aplikacija (programa zavisnih od harvera na kom se izvršavaju i operativnih
sistema), i biblioteka napisanih u C/C++ i mašinskom jeziku.
Na taj nacin rješavaju se problemi u potrebi za funkcionalnošću koja nedostaje Javi, u komunikaciji
na nižem nivou od JVM, a koja je žrtvovana u ime portabilnosti Jave meĎu različitim
platformama.
1.2.1 PRIMJENA JNI
Čak i mnoge standardne Java biblioteke koriste JNI, i na taj način isporučuju odgovarajuće
funkcionalnosti, npr. metode za rad sa fajlovima i sa zvukom.
JNI omogućava native metodama da koriste Java objekte, na način na koji se to čini i u Java
programima, dakle, native metod može instancirati Java objekte, ili primati kao parametre
objekte koji su već instancirani u Java programu, raditi sa njima, pozivati njihove metode, i
mjenjati ih.
Sa druge strane, često se javlja potreba da već imamo native kod napisan, i dostupan preko
biblioteka, i Javu koristimo kao interfejs za pristup tim metodama, odnosno funkcionalnostima
koje ove biblioteke pružaju.
Ukoliko se radi o vremenski zahtjevnoj operaciji, obzirom na niži nivo apstrakcije native koda,
prevedenim u mašinski kod i sposobnim da iskoristi sve prednosti hardvera na kom se izvršava,
jasno je da će ovakav kod izvršavati brže, npr. kompleksni matematički obračuni. U novije
vrijeme, ova razlika je sve manja, jer se JVM usavršava, pa je danas moguće da ce se u nekim
slučajevima JVM bajt kod izvršavati brže od ekvivalentnog native koda.
1.2.2. PROBLEMI
Postoji niz problema sa kojima se suočavamo, upotrebom JNI, kao npr.:
greške u upotrebi JNI mogu destabilizovati čitavu JVM, a koje je ponekad teško otkriti ili
debug-ovati
samo aplikacije i potpisani apleti mogu koristiti JNI
aplikacija gubi na portabilnosti upotrebom JNI, moguće rješenje je da napišemo posebnu
implementaciju za svaku platormu, a onda da koristimo AbstractFactory pattern, zavisno od
platfome
JNI ne obezbjeĎuje Garbage Collector, za resurse koji nisu u direktnoj vezi sa JVM, znači
moramo voditi računa o svim objektima instanciranim u okviru native metoda, i njihovom
uništavanju
provjera grešaka je obaveza pri ovakvoj implementaciji, obzirom da ove greške mogu
oboriti čitavu JVM
koristi se modifikovani UTF-8, u metodama JNI poput NewStringUTF i sl.
1.2.3. NAČIN NA KOJI FUNKCIONIŠE JNI
Kada JVM poziva native funkciju, prosijeĎuje se JNIEnv pokazivač, tipa jobject, i argumenti
funkcije deklarisani od strane Java metode. Ovaj pokazivač je struktura koja sadrži interfejs ka
JVM, odnosno svim neophodnim metodama za interakciju sa JVM i rad sa Java objektima. U
[SE411-INTEGRATIVNO PROGRAMIRANJE U DVA PROGRAMSKA JEZIKA C++/JAVA]
December 16, 2010
10 | S t r a n a
suštini, bilo što što Java kod može da uradi, može da se uradi i preko JNIEnv, ali na dosta
komplikovaniji način.
Primjer upotrebe je instanciranje objekata, kreiranje stringova, i sl., o čemu ce biti riječi u drugom
dijelu izlaganja. Kod napisan u C++ koji koristi JNI je nešto čistiji u odnosu na C, jer je C++
objektno orjentisan jezik, poput Jave.
1.2.4. MAPIRANJA NATIVE I JAVA TIPOVA PODATAKA
Native tipovi se mogu mapirati na Java proste tipove podataka, i obrnuto kao u sledećoj tabeli. Za
druge tipove, potpis je po obrazcu L<naziv paketa>.<naziv klase>;, npr. za String
Ljava/lang/String;
Ukoliko se radi o nizu koristi se notacija [ ispred potpisa tipa, npr. za niz cjelih brojeva, pišemo [I.
Tabela 1. Mapirani tipovi
Native tip Java Tip Opis “Signature”
tipa
unsigned char jboolean neoznačenih 8 bita Z
signed char jbyte označenih 8 bita B
unsigned short jchar neoznačenih 16 bita C
short jshort označenih 16 bita S
int Jint označenih 32 bita I
long jlong označenih 64 bita J
float jfloat 32 bita F
double jdouble 64 bita D
Ovi tipovi takoĎe podrazumjevaju implicitnu konverziju meĎusobno ekvivalentnih Java/native tipova
npr. jint nije potrebno konvertovati u int da bi se koristio kao int. Ovo ne važi uvijek, npr. za
stringove, upotreba jstring na mjestu char * dovešće do pucanja JVM. Izuzetak od pravila
su i nizovi, gdje je potrebno koristiti posebne konstrukcije, kao što ce biti navedeno u primjeru
kasnije.
1.2.4. OSTALE PRIMJENE
Ne samo da native i Java kod mogu da se zajedno koriste, vec je moguće i crtati direktno na Java
Canvas objekat, upotrebom Java AWT native interfejsa. Sem toga, moguće je i direktno
pristupati assembly kodu, i obrnuto iz assembly koda pristupati Java aplikaciji.
[SE411-INTEGRATIVNO PROGRAMIRANJE U DVA PROGRAMSKA JEZIKA C++/JAVA]
December 16, 2010
11 | S t r a n a
1.3 KNI-K NATIVE INTERFACE
Zbog univerzalne namjene JNI, često se ovaj API postavlja kao previše skup, po pitanju utroška
memorije, i performansi. Uz to, pojavljuju se i sigurnosni problemi, obzirom na nedostatak Java
2 security modela.
Cilj KNI je da izdvoji podskup funkcionalnosti JNI, koji su odgovarajući za ureĎaje sa ograničenom
memorijom, skromnijih hardverskih mogućnosti. Obzirom da je namjenjen da bude lakši po
pitanju zahtjeva, prati konvencije JNI koliko je to u duhu samog API-ja, dok je konvencija
Da bi kreirali potpise metoda, koristićemo i javap.exe, na sledeći način:
javap -s rs.edu.fit.se411.jni.JniExample
Kako će se program vremenom mjenjati, preporuka je da se ove komande sačuvaju u okviru
Eclipse pod External Tools.
4 Native program-Napisan za hardver, ili za operativni sistem, na niskom nivou, kompajliranjem prevodi se u
mašinski kod. 5 Dll-Dynamic-link Library, je Microsoft implementacija za koncept djeljene biblioteke, u MS Windows
operativnim sistemima, i OS/2. Moguće ekstenzije su DLL, OCX-ActiveX kontrole, koje pamtimo još iz vremena Visual Basic 6 i njihove registracije, i DRV (sistemski drajveri).