Java -alkuperäinen käyttöliittymä - Java Native Interface
In ohjelmistojen suunnittelu , The Java Native Interface ( JNI ) on ulkomainen toiminto rajapintana ohjelmoinnin puitteissa , jonka avulla Java- koodin käytössä jossakin Java-virtuaalikone (JVM) soittaa ja kutsuttavaksi natiiveja ohjelmia (ohjelmat erityisesti laitteiston ja käyttöjärjestelmän Platform) ja kirjastot, jotka on kirjoitettu muilla kielillä, kuten C , C ++ ja assembly .
Tavoitteet
JNI avulla ohjelmoijat kirjoittaa kotoisin menetelmiä käsitellä tilanteita, kun sovellus ei voida kirjoitettu kokonaan Java-ohjelmointikielellä, esim standardin Java -luokan kirjastossa ei tue lavan erityispiirteet tai ohjelman kirjastoon. Sitä käytetään myös muokkaamaan olemassa olevaa (toisella ohjelmointikielellä kirjoitettua) sovellusta Java -sovellusten käytettäväksi. Monet kirjaston vakioluokista ovat riippuvaisia JNI: stä tarjotakseen kehittäjälle ja käyttäjälle toiminnallisuutta, esim. Tiedoston I/O ja äänitoiminnot. Suorituskyky- ja käyttöympäristöherkkien sovellusliittymien sisällyttäminen vakiokirjastoon sallii kaikkien Java-sovellusten käyttää tätä toimintoa turvallisesti ja alustasta riippumatta.
JNI -kehyksen avulla alkuperäinen menetelmä voi käyttää Java -objekteja samalla tavalla kuin Java -koodi käyttää näitä objekteja. Alkuperäinen menetelmä voi luoda Java -objekteja ja sitten tarkastella ja käyttää näitä objekteja tehtäviensä suorittamiseen. Alkuperäinen menetelmä voi myös tarkastella ja käyttää Java -sovelluskoodin luomia objekteja.
Vain sovellukset ja allekirjoitetut appletit voivat kutsua JNI: tä.
Sovellus, joka perustuu JNI: hen, menettää Java -alustan siirrettävyyden (osittainen kiertotapa on kirjoittaa erillinen JNI -koodin toteutus kullekin alustalle ja saada Java tunnistamaan käyttöjärjestelmä ja lataamaan oikea ajon aikana).
Natiivikoodin käyttöliittymä ei voi olla vain Java -käyttöliittymä, vaan se voi hyödyntää myös Java -ohjelmaa Canvas, mikä on mahdollista Java AWT -käyttöliittymän avulla . Prosessi on melkein sama, vain muutamilla muutoksilla. Java AWT Native Interface on käytettävissä vain J2SE 1.3: n jälkeen.
JNI mahdollistaa myös suoran pääsyn kokoonpanokoodiin ilman C -siltaa. Java -sovellusten käyttö kokoonpanosta on mahdollista samalla tavalla.
Design
JNI -kehyksessä natiivitoiminnot toteutetaan erillisissä .c- tai .cpp -tiedostoissa. (C ++ tarjoaa hieman yksinkertaisemman käyttöliittymän JNI: n kanssa.) Kun JVM kutsuu funktion, se välittää JNIEnvosoittimen, jobjectosoittimen ja kaikki Java -menetelmän ilmoittamat Java -argumentit. Esimerkiksi seuraava muuntaa Java -merkkijonon natiiviksi merkkijonoksi:
extern "C"
JNIEXPORT void JNICALL Java_ClassName_MethodName
(JNIEnv *env, jobject obj, jstring javaString)
{
const char *nativeString = env->GetStringUTFChars(javaString, 0);
//Do something with the nativeString
env->ReleaseStringUTFChars(javaString, nativeString);
}
envOsoitin on rakenne, joka sisältää rajapinnan JVM. Se sisältää kaikki toiminnot, joita tarvitaan vuorovaikutukseen JVM: n ja Java -objektien kanssa. Esimerkki JNI -toiminnoista ovat natiivimatriisien muuntaminen Java -matriiseiksi/Java -matriiseiksi, natiivien merkkijonojen muuntaminen Java -merkkijonoiksi/-jonoiksi, objektien näyttäminen, poikkeusten heittäminen jne. Periaatteessa kaikki, mitä Java -koodi voi tehdä, voidaan tehdä käyttämällä JNIEnv, vaikkakin huomattavasti vähemmän helposti.
Argumentti objviittaa Java -objektiin, jonka sisällä tämä alkuperäinen menetelmä on ilmoitettu.
Alkuperäiset tietotyypit voidaan yhdistää Java -tietotyyppeihin tai niistä. Yhdistetyypeille, kuten objekteille, matriiseille ja merkkijonoille , alkuperäisen koodin on nimenomaisesti muunnettava tiedot kutsumalla menetelmiä JNIEnv.
JNI -ympäristön osoitin ( JNIEnv* ) välitetään argumenttina jokaiselle Java -menetelmään yhdistetylle natiivifunktiolle, mikä mahdollistaa vuorovaikutuksen JNI -ympäristön kanssa alkuperäisessä menetelmässä. Tämä JNI -rajapinnan osoitin voidaan tallentaa, mutta se pysyy voimassa vain nykyisessä säikeessä. Muiden säikeiden on ensin kutsuttava AttachCurrentThread (), jotta ne voidaan liittää VM: ään ja hankkia JNI -rajapintaosoitin. Kun natiivi on liitetty, se toimii kuin tavallinen Java -säie, joka toimii natiivimenetelmässä. Alkuperäinen säie pysyy kiinni virtuaalikoneessa, kunnes se kutsuu DetachCurrentThread () irrottaakseen itsensä.
JNI-kehys ei tarjoa automaattista roskien keräämistä muille kuin JVM-muistiresursseille, jotka on jaettu alkuperäisellä puolella suoritettavan koodin avulla. Näin ollen natiivi sivukoodi (kuten kokoonpanokieli) ottaa vastuun natiivikoodin hankkimien muistiresurssien nimenomaisesta vapauttamisesta.
Linux- ja Solaris -alustoilla, jos alkuperäinen koodi rekisteröi itsensä signaalinkäsittelijäksi, se voi siepata JVM: lle tarkoitettuja signaaleja. Vastuuketju voidaan sallia koodiksi paremmin välisen toimivat JVM. Windows-alustoilla Strukturoitujen poikkeusten käsittelyä (SEH) voidaan käyttää natiivikoodin käärimiseen SEH try/catch -lohkoihin koneen (CPU/FPU) tuottamien ohjelmistokeskeytysten kaappaamiseksi (kuten NULL-osoittimen käyttörikkomukset ja jako nollalla -toiminnot) ), ja käsitellä näitä tilanteita ennen kuin keskeytys levitetään takaisin JVM: ään (eli Java -sivukoodiin), mikä todennäköisesti johtaa käsittelemättömään poikkeukseen.
NewStringUTF-, GetStringUTFLength-, GetStringUTFChars-, ReleaseStringUTFChars- ja GetStringUTFRegion-toimintojen koodaus on "modifioitu UTF-8", joka ei kelpaa UTF-8 kaikille tuloille, mutta todella erilainen koodaus. Null merkki (U + 0000) ja codepoints ei mainita Basic Multilingual Plane (suurempi tai yhtä suuri kuin U + 10000, eli ne edustettuina korvike paria UTF-16) on koodattu eri tavoin modifioitu UTF-8. Monet ohjelmat käyttävät näitä toimintoja väärin ja käsittelevät palautetut tai toimintoihin siirretyt UTF-8-merkkijonot vakio-UTF-8-merkkijonoina muokattujen UTF-8-merkkijonojen sijaan. Ohjelmien tulisi käyttää NewString-, GetStringLength-, GetStringChars-, ReleaseStringChars-, GetStringRegion-, GetStringCritical- ja ReleaseStringCritical-toimintoja, jotka käyttävät UTF-16LE-koodausta pikku-endian-arkkitehtuureissa ja UTF-16BE-koodausta iso-endian-arkkitehtuureissa ja käyttävät sitten UTF-16-koodia 8 muuntorutiini.
Kartoitustyypit
Seuraavassa taulukossa esitetään tyypin kartoitus Java (JNI) ja natiivikoodi.
| C Tyyppi | Java -kielityyppi | Kuvaus | Kirjoita allekirjoitus |
|---|---|---|---|
| allekirjoittamaton char uint8_t |
jboolean | allekirjoittamaton 8 bittiä | Z |
| allekirjoitettu char int8_t |
jbyte | allekirjoitettu 8 bittiä | B |
| allekirjoittamaton lyhyt uint16_t |
jchar | allekirjoittamaton 16 bittiä | C |
| lyhyt int16_t |
j lyhyt | allekirjoitettu 16 bittiä | S |
| int int32_t |
jint | allekirjoitettu 32 bittiä | Minä |
|
pitkä pitkä |
jlong | allekirjoitettu 64 bittiä | J |
| kellua | jfloat | 32 bittiä | F |
| kaksinkertainen | kaksinkertainen | 64 bittiä | D |
| mitätön | V |
Lisäksi allekirjoitus "L fully-qualified-class ;"tarkoittaisi tällä nimellä yksilöllisesti määriteltyä luokkaa; esim. allekirjoitus "Ljava/lang/String;"viittaa luokkaan java.lang.String. Lisäksi [allekirjoituksen etuliite tekee tämän tyyppisestä taulukosta; esimerkiksi, [Itarkoittaa int array tyyppi. Lopuksi voidallekirjoitus käyttää Vkoodia.
Nämä tyypit ovat vaihdettavissa. Voidaan käyttää jintsiellä, missä tavallisesti käytät int, ja päinvastoin, ilman tyyppikuvitusta . Java -merkkijonojen ja matriisien yhdistäminen alkuperäisiin merkkijonoihin ja matriiseihin on kuitenkin erilainen. Jos jstringkäytetään, jossa char *olisi, koodi saattaa kaatua JVM.
Esitys
JNI kärsii huomattavista yleiskustannuksista ja suorituskyvyn menetyksestä tietyissä olosuhteissa:
- Funktion kutsut JNI -menetelmiin ovat kalliita, varsinkin kun menetelmää kutsutaan toistuvasti.
- JVM ei sisällä natiivimenetelmiä, eikä menetelmää voi kääntää JIT: ksi , koska menetelmä on jo koottu.
- Java -matriisi voidaan kopioida pääsyä varten natiivikoodiin ja myöhemmin kopioida takaisin. Hinta voi olla lineaarinen taulukon koossa.
- Jos menetelmä välittää objektin tai sen on tehtävä soittopyyntö, alkuperäinen menetelmä todennäköisesti soittaa omia puheluitaan JVM: ään. Java -kenttien, -menetelmien ja -tyyppien käyttäminen alkuperäisestä koodista vaatii jotain vastaavaa kuin pohdintaa . Allekirjoitukset määritetään merkkijonoina ja niitä haetaan JVM: ltä. Tämä on sekä hidasta että virhealtista.
- Java -merkkijonot ovat objekteja, niillä on pituus ja ne on koodattu. Merkkijonon käyttäminen tai luominen voi vaatia O (n) -kopion.
Vaihtoehdot
Microsoftin oma Java -virtuaalikoneen ( Visual J ++ ) toteutus sisälsi samanlaisen mekanismin natiivikoodin kutsumiseksi Javalta , nimeltään Raw Native Interface ( RNI ). Lisäksi sillä oli helppo tapa soittaa olemassa olevaan natiivikoodiin, joka ei ollut tietoinen Javasta, kuten (mutta ei rajoittuen) Windows -sovellusliittymään, nimeltään J/Direct . Kuitenkin Sunin ja Microsoftin välisen oikeudenkäynnin jälkeen tästä toteutuksesta Visual J ++: ta ei enää ylläpidetä.
RNI oli vähemmän hankala käyttää kuin JNI, koska kirjanpitoa Java -ympäristön osoittimella ei tarvittu. Sen sijaan kaikkiin Java -objekteihin voidaan päästä suoraan. Tämän helpottamiseksi käytettiin työkalua, joka loi otsikkotiedostot Java -luokista. Samoin J/Direct oli helpompi käyttää kuin tarvittavan natiivikirjaston ja JNI: n käyttäminen.
Java Native Access (JNA) on yhteisön kehittämä kirjasto, joka tarjoaa Java-ohjelmille helpon pääsyn jaettuihin alkuperäisiin kirjastoihin ilman JNI: tä.
Katso myös
Viitteet
Bibliografia
- Gordon, Rob (maaliskuu 1998). Essential Jni: Java Native Interface (1. painos). Prentice Hall . s. 498. ISBN 0-13-679895-0.
- Liang, Sheng (20. kesäkuuta 1999). Java (TM) Native Interface: Programmer's Guide and Specification (1. painos). Prentice Hall . s. 320. ISBN 0-201-32577-2.