Java-virtuaalikone

Java-virtuaalikone (engl. Java Virtual Machine, JVM) on abstrakti kone (virtuaalikone), joka suorittaa sille käännettyjä Java-ohjelmia. Virtuaalikone on toteutettu ohjelmallisesti oikean laitteiston ja käyttöjärjestelmän päällä ajettavaksi. Java-kielellä tehdyt ohjelmat käännetään tavukoodiksi ja suoritetaan JVM:llä oikeassa ympäristössä.

Java-virtuaalikoneen avulla voidaan ajaa myös eräillä muilla ohjelmointikielillä tehtyjä ohjelmia, jotka on käännetty JVM:n tukemaksi tavukoodiksi. JVM-spesifikaatio () kuvaa JVM-toteutuksen formaaliset vaatimukset. Spesifikaatio varmistaa Java-ohjelmien yhteentoimivuuden eri toteutusmuodoissa, jotta Java-kehitystyökaluja (JDK) käyttävien ohjelmiston kehittäjien ei tarvitse huolehtia taustalla olevan laitteistoalustan erilaisuuksista. 

 JVM:n tarkka määrittely 
Määritelmän mukaisesti Java virtuaalikone on abstrakti (virtuaalinen) tietokone. Se on osa Javan runtime-ympäristöä. Ympäristössä käytetään jätteiden keräysalgoritmia. Siinä ei ole eritelty mitään muita Javan sisäisiä optimointeja, joita Javan virtuaalikoneen ohjeet käyttävät. Tärkein syy jättää tämä pois on se, että virtuaalitietokoneen toteuttajia ei rajoiteta tarpeettomasti. Mikä tahansa Java-ohjelma voidaan ajaa jonkin konkreettisen toteutuksen sisällä, joka sisältää Javan virtuaalitietokoneen yksityiskohdat. 

Javan Standard Edition (J2SE) 5.0 versiosta lähtien muutoksia JVM:n tarkkaan määrittelyyn on kehitetty Java Community Process:in (JSR 924) alaisuudessa. Vuodesta 2006 lähtien JSR 202:n ehdottamien luokkatiedoston muutosten tukemiseksi suoritetaan JSR 924:n ylläpitolisenssiversiona. Tarkka määritelmä JVM:lle julkaistiin "blue book" -kirjana, jonka alkupuhe toteaa:

Yksi Oraclen JVM:istä on nimetty HotSpotiksi. Toinen on periytynyt BEA Systemsiltä ja sen nimi on JRockit. Oracle omistaa Java-tavaramerkin ja voi sallia sen käytön implementaatiopaketeissa varmistaakseen, että ne ovat täysin yhteensopivia Oraclen specifikaation kanssa.

 Luokkalataaja 
Yksi organisaatioyksikkö JVM:n koodissa on luokka. Luokkalataajan käyttöönottajan tulee voida tunnistaa ja ladata mitä tahansa, jota mukautuu Java-luokan tiedostotyyppiin. Minkä tahansa toteutuksen tulee olla vapaa tunnistamaan muita kaksiosaisia tyylejä lukuun ottamatta luokkatiedostoja, mutta sen tulee kuitenkin tunnistaa luokkatiedostot. 

Luokkalataaja suorittaa kolme perus aktiviteettia tässä tarkassa järjestyksessä:

 Lataaminen: löytää ja tuo tyypin binääritiedot
 Linkittäminen: suorittaa verifioinnin, valmistelun ja valikoiduissa tilanteissa resoluution säädön.
 Verifiointi: Varmista tuodun tyypin oikeinkirjoituksen
 Valmistelu: Allokoi muistia luokkan muuttujille ja alustaa muistin perus arvoihin
 Resoluutio: Muuttaa tyyppien symboliset maininnat suorin mainintoihin.
 Käyttöönotto: Herättää Java koodin, joka käyttöönottaa luokan muuttujat niiden tiettyihin lähtöarvoihin.

Yleisesti käytössä on kolme luokkalataajatyyppiä. Ne ovat bootstrap-luokkalataaja, extension-luokkalataaja sekä System / Application -luokkalataaja.

 JVM arkkitehtuuri 
JVM käyttää tarkoin määriteltyjä tietotyyppejä, joiden määritelmät löytyvät Java Virtual Machine teknisistä tiedoista. Tietotyypit vodaan jakaa alkeellisiin ja viittaus tyyppeihin. Alkeellisiin Tietotyyppeihin kuuluu mm. kokonaisluvut ja liukuluvut. Alun perin JVM oli tarjolla vain 32 bittisillä tietokoneilla, josta johtuen esimerkiksi long ja double tyyppiset tietotyypit, jotka vaativat 64 bittiä ovat tuettuja, mutta ne tallennetaan kahdelle muistipaikalle, jotka molemmat on 32 bittisiä. Muun muassa char ja short tyyppisiä tietotyyppejä käytetään 32 bittisinä kokonaislukuina. Uusimmat JVM julkaisut tukevat 64 bittiä, joten on mahdollista käyttää joko 32 bittistä tai 64 bittistä JVM:ää 64 bittisellä käyttöjärjestelmällä. Merkittävin hyöty 64 bittisen ympäristön käytössä on suurempi osoite avaruus eli yksilöllisten osoitteiden määrä. Se mahdollistaa paljon suuremman Java Threads määrän käytön, mikä voi olla tarpeellista joidenkin suurin ohjelmien tekemisessä. 32 bittinen JVM on kuitenkin jonkin verran tehokkaampi verrattuna 64 bittiseen JVM versioon.

JVM sisältää niin sanotun roskien kerääjän (garbage collector), joka poistaa muistista sellaisia olioita ja tietoja, joita ei enää tarvita ja vapauttaa täten muistia ohjelman käytettäväksi. Koodi, vakiot ja muu luokkien sisältämä tieto ei kuitenkaan välttämättä kuulu garbage collectorin piiriin, jolloin niitä ei välttämättä hävitetä. Kuitenkin joka kerta kun metodia kutsutaan, luodaan uusi rakenne, joka kuitenkin hävitetään kun, metodista poistutaan. 

 Tavukoodin ohjeet 
JVM:llä on ohjeet seuraaville tehtäväryhmille: 
Lataa ja varastoi
Aritmeettinen
Tyyppimuunnos
Olion luonti ja manipulointi
Operandi pino hallinta (push / pop)
Ohjauksen siirto (haaroittuminen)
Metodin kutsuminen ja palauttaminen
Poikkeusten heitto (throw exception)
Näyttöön perustuva samanaikaisuus

Päämääränä on binaarinen yhteensopivuus. Jokainen tietty isäntäkäyttöjärjestelmä tarvitsee oman toteutuksensa JVM:stä ja suoritusajasta. Nämä JVM:t tulkitsevat tavukoodin semanttisesti samalla tavalla, mutta varsinainen toteutus voi olla erilainen. Monimutkaisempi kuin vain tavukoodin emulointi on yhteensopivuus ja tehokas Java core API:n toteutus, jonka täytyy olla kartoitettu jokaiseen isäntäkäyttöjärjestelmään.

Nämä ohjeet toimivat joukolla yleisiä abstrakteja tietotyyppejä minkään tietyn käskysarja-arkkitehtuurin alkuperäisten tietotyyppien sijaan. 

 Tavukoodi vahvistaja 
Javan perusfilosofia on, että se on turvallinen siltä kannalta, että mikään käyttäjäohjelma ei voi kaataa isäntäkonetta tai muuten häiritä isäntätietokoneen muita toimintoja sopimattomasti ja että on mahdollista suojata tiettyjä luotettuun koodiin kuuluvia metodeja ja tietorakenteita pääsyltä tai korruptiolta epäluotetun koodin toimesta, joka suoritetaan samassa JVM:ssä. Lisäksi tavalliset ohjelmoijavirheet, jotka usein johtavat tietokorruptioon tai arvaamattomaan käytökseen, kuten pääsy taulukon päähän tai alustamattoman osoittimen käyttäminen, eivät saa tapahtua. Useat Javan toiminnot yhdistettynä tarjoavat tämän turvallisuuden, mukaan lukien luokkakaavio, roskakerätty (garbage-collected) pino ja vahvistaja.

JVM vahvistaa kaiken tavukoodin ennen kuin se suoritetaan. Tämä todennus sisältää pääasiassa kolmenlaisia tarkistuksia:
 Haaraumat ovat aina oikeisiin paikkoihin
 Tiedot alustetaan aina ja viittaukset ovat aina tyyppiturvallisia
 Pääsyä yksityisiin tai pakattuihin tietoihin ja metodeihin on tiukasti ohjattu

Kaksi ensimmäistä näistä tarkistuksista tehdään ensisijaisesti vahvistusvaiheen aikana, kun luokka on ladattu ja tehty kelvolliseksi käyttää. Kolmas on ensisijaisesti tehty dynaamisesti, kun tietokohteita ja luokkien metodeja käyttää ensimmäisen kerran joku muu luokka.

 JVM:n tukemat kielet 
JVM-kieliä on useita. JRuby ja Jython ovat kenties tunnetuimpia JVM-käännöksiä Ruby- ja Python-kielistä. Java-tavukoodiksi kääntyviä vakiintuneita kieliä ovat muun muassa Clojure, Apache Groovy, Scala ja Kotlin. JVM-kielten merkittävä piirre on, että ne ovat yhteensopivia toistensa kanssa, joten esimerkiksi Scala-kirjastoja voidaan käyttää Java-ohjelmien kanssa ja päinvastoin. 

 Java Runtime Environment 
Java Runtime Environment (JRE) on vapaasti saatavilla oleva ohjelmisto, joka sisältää itsenäisen virtuaalikoneen (HotSpot), standardikirjaston (Java Class Library), ja konfigurointiohjelman. Se on yleisin JVM-ajoympäristö. 

Avoimen lähdekoodin ympäristöjä ovat OpenJDK GPL-2.0 ohjelmistolisenssillä linkittämispoikkeuksella ja Eclipse (aikaisemmin IBM) OpenJ9.

Android-käyttöjärjestelmää käyttävät järjestelmät kääntävät ohjelmat Android Runtime (ART) -ajoympäristölle, joka kääntää ohjelmaa natiiville konekielelle: aiemmin Androidissa on käytetty Dalvik-virtuaalikonetta.

 JVM verkkoselaimessa 
Kun Java-alusta oli vielä vasta elinkaarensa alussa, JVM:ää markkinoitiin verkkoteknologiana Rich Web Applications -sovellusten luomiseen. Vuodesta 2018 lähtien useimpien verkkoselaimien ja verkkoselaimia yhdistävien käyttöjärjestelmien mukana ei toimiteta Java-laajennusta, eivätkä ne sallineet muiden kuin Flash -laajennusten sivulatausta . Java-selainlaajennus poistettiin käytöstä JDK 9:ssä. 

NPAPI Java -selainlaajennus oli suunniteltu sallimaan JVM suorittaa niin sanottuja Java-sovelmia, jotka on upotettu HTML-sivuille. Niille selaimille, joihin laajennus on asennettu, voi sovelma voi piirtyä sille osoitetun sivun suorakaiteen muotoiseen alueeseen. Koska laajennus sisältää JVM:n, Java-sovelmat eivät rajoitu vain Java-ohjelmointikieleen, sillä mikä tahansa JVM:ään kohdistettu kieli voi toimia laajennuksessa. Rajoitettu joukko sovellusliittymiä sallii sovelmien pääsyn käyttäjän mikrofoniin tai 3D-kiihdytykseen, vaikka sovelmat eivät pysty muokkaamaan sivua sen suorakulmaisen alueen ulkopuolella. 

Kesäkuuhun 2015 mennessä oli W3Techsin mukaan Java-sovelman ja Microsoft Silverlightin käyttö  pudonnut 0,1 prosenttiin kaikilla verkkosivuilla. Samaan aikaan Flashin käyttö oli pudonnut 10,8 prosenttiin. 

 JavaScript JVM:t ja tulkit
Toukokuusta 2016 lähtien JavaPoly on sallinut käyttäjien tuoda muokkaamattomia Java-kirjastoja ja kutsua niitä suoraan JavaScriptistä. JavaPoly sallii verkkosivustojen käyttää muokkaamattomia Java-kirjastoja, vaikka käyttäjän tietokoneeseen ei olisi asennettu Java. 

 Käännös JavaScriptiin 

JavaScript-suoritusnopeuden jatkuva lisääntyminen ja mobiililaitteiden sellainen käyttö, joka ei tue laajennuksia, aiheuttaa ongelmia, jotka pyritään ratkaisemaan JavaScriptiin kääntämisen avulla. On mahdollista kääntää joko lähdekoodi tai JVM-tavukoodi JavaScriptiksi.

JVM-tavukoodin kääntäminen, joka on universaali kaikissa JVM-kielissä, mahdollistaa kielen olemassa olevan kääntäjän pohjalta tavukoodauksen. Tärkeimmät JVM-tavukoodit JavaScript-kääntäjiin ovat TeaVM, joka on Dragome Web SDK:n sisältämä kääntäjä, Bck2Brwsr, ja j2js-kääntäjä. 

Johtavia kääntäjiä JVM-kielistä JavaScriptiin ovat Google Web Toolkit -työkaluihin kuuluva Java-JavaScript-kääntäjä,  Clojurescript (Clojure), GrooScript (Apache Groovy), Scala.js (Scala) ja useat muut. 

 Lähteet 

Luokka:Java
Luokka:Virtuaalikoneet