Prostim rečima i ručno nacrtanim ilustracijama upoznaj JVM — šta je zapravo JVM?
„Erge, još dok si pričao o prvoj liniji Java koda, hello world, pomenuo si JVM; već tada sam želela da znam šta je JVM zapravo, ali si rekao da je to vrlo velika tema koja će doći kasnije, posebno. Sad sam savladala osnove Jave, a i konkurentno programiranje, pa da li danas učimo JVM?” — rekla mi je Sanmej posle jednog gutljaja mlečnog čaja od žitarica i kakaa.
„Dobro, Sanmej, u ovom tekstu ću te upoznati sa tim šta je JVM. JVM je u Java sistemu veoma važan i donekle zahtevan deo znanja, ali svaki programer koji želi da bude bolji treba da ga savlada. Posebno kolege koji žele u veliku ili srednju firmu — na intervjuima u takvim firmama JVM ima veliki udeo. Prosto ću ti iz «Vodiča za Java intervjue» izvući jedan snimak da osetiš o čemu se radi”, odgovorio sam.

„U intervjuima za pripravnike JVM i dalje ima veoma veliki udeo; a za one koji već rade, ukoliko projekat naiđe na curenje memorije ili skok CPU-a, često se upravo preko JVM nadzora performansi problem locira i rešava. Hajde da krenemo!” — dodao sam.
Sanmej, iz Kratke istorije razvoja Jave znaš da je Sun 1991. godine formirao projektni tim pod imenom „Green”, na čelu sa Džejmsom Goslingom (James Gosling), sa ciljem da razvije arhitekturu programa sposobnu da radi na različitim potrošačkim elektronskim uređajima.
U početku je tim nameravao da koristi C++, ali C++ nije ispunjavao zahtev za višeplatformski rad; na primer, Hello.exe kompajliran pod Windows sistemom ne može se direktno izvršiti pod Linux okruženjem.

U to vreme C++ je već bio veoma popularan, ali nije podržavao višeplatformski rad, pa se morao otkloniti.
Šta onda?
Sanmej, da li si čula za interpretaire (interpretatore)? (Verovatno nisi.) To je ono što svaku liniju koda pretvara u mašinski kod i zatim je izvršava; na primer, Python i Ruby koriste interpretaire.
„Onda na svaki operativni sistem instaliramo po jedan interpreter i time je cilj višeplatformskog rada postignut”, ubacila se Sanmej.

„Ali interpreter ima i manu — ne može kao kompajler da optimizuje vrući kod, pa program na mašini radi brže”, odgovorio sam.
Šta onda?
Neka bude hibrid — neka i kompajler i interpreter rade zajedno!

Kompajler prevodi Java izvorni kod u bajtkod, a Java virtuelna mašina pretvara bajtkod u mašinski kod. Pri pretvaranju može se uraditi neka kompresija ili optimizacija preko JIT-a, pa program radi znatno brže.

- Java virtuelna mašina: Java Virtual Machine, skraćeno JVM — to je žarište onoga što ćemo ubrzo učiti.
- Bajtkod: Bytecode, o čemu će biti reči detaljnije.
- JIT: Just-In-Time, just-in-time kompajler, o kom ćemo detaljno govoriti kasnije.
Tako je postignut i cilj višeplatformskog rada i optimizacija performansi — oba u jednom!
„Zašto se Java virtuelna mašina zove baš Java virtuelna mašina?” — Sanmej je postavila prilično čudno pitanje.
Virtuelna mašina je, kao što ime kaže, virtuelna mašina (koliko god bleda objašnjenju bila) — u svakom slučaju, mašina koja se ne može videti ni dotaknuti, jedan naziv naspram fizičke mašine; zamisli je kao čudovište koje izvršava bajtkod.
Sećam se za vreme fakulteta, pošto nisam imao Linux okruženje, a morao sam da probam neke komande, instalirao bih na Windows virtuelnu mašinu sa Linuxom — ovaj JVM je nešto slično.
Da se razumemo, mi pišemo Java kod i kompajliramo Java kod ne zato da bi radio na Linuxu, Windowsu ili MacOS-u, već da bi radio na JVM-u.
JVM porodica
Jedva što sam to završio, Sanmej pita: „A koje sve postoje Java virtuelne mašine?”
Pogledaj sledeću mapu uma i biće ti jasno.

Osim Hotspot VM, koju često viđamo i čujemo, postoji još mnogo njih; evo ukratko o svakoj.
- Sun Classic: prva Java virtuelna mašina na svetu namenjena komercijalnoj upotrebi, ali joj je efikasnost izvršavanja bila niska, zbog čega je jaz u performansama između Java programa i C/C++-a bio veliki; otuda potiče i stereotip „Java je spora” koji je ostavila nasleđenicama.
- Exact VM: da bi se poboljšala efikasnost Classic-a, tim za virtuelne mašine u Sun-u objavio je ovu virtuelnu mašinu na Solarisu (operativni sistem nalik Unix-u koji je razvio Sun); njen sistem izvršavanja sadržao je detekciju vrućeg koda, just-in-time kompilaciju i sl., ali nije bio sasvim zreo. Sun Classic je potpuno odbačen u JDK-u 1.4, a Exact VM još i ranije; zamenio ih je upravo HotSpot VM — takva je sudbina.
- Mobile VM: razvoj Jave na mobilnim telefonima (koje su podelili Android i iOS) nije bio naročito uspešan, pa je ugled Mobile VM-a prilično nizak.
- Embedded VM: virtuelna mašina za ugrađene uređaje.
- BEA JRockit: nekad nazivana „najbržom Java virtuelnom mašinom na svetu”, a nakon što ju je Oracle otkupio, više se o njoj nije čulo.
- IBM J9 VM: kad se pomene IBM, gotovo svi programeri znaju — to je džin, pa je i njena virtuelna mašina moćna; u pogledu razdvajanja odgovornosti i modularnosti bolja je od HotSpot-a. Trenutno je poklonjena Eclipse fondaciji.
- BEA Liquid VM: virtuelna mašina koju je BEA razvio da radi direktno na sopstvenom sistemu, zaobilazeći operativni sistem i komunicirajući neposredno sa hardverom, čime je u većoj meri iskorišćavala mogućnosti hardvera. No, u suštini je koristila JRockit, pa je sa nestankom JRockit-a i Liquid VM izašao iz istorijske pozornice.
- Azul VM: virtuelna mašina koju je Azul, nakon brojnih poboljšanja nad HotSpot-om, napravio da radi na svom specijalnom hardveru. Od 2010. Azul je prešao sa hardvera na softver i objavio Zing virtuelnu mašinu, veoma snažnu u pogledu performansi.
- Apache Harmony i Google Android Dalvik VM nisu, strogo gledano, Java virtuelne mašine, ali su snažno podstakli razvoj Java virtuelnih mašina. Ipak, vreme je prevalilo i njih.
- Microsoft JVM: u ranim danima Java apleta, razvio je Microsoft, kako bi IE podržao razvoj apleta, sopstvenu Java virtuelnu mašinu. Možeš li da veruješ? Microsoft JVM postoji samo u Windows verziji i sa idejom „kompajliraj jednom, pokreni bilo gde”, koju zastupa JVM, nema nikakve veze. Ključno je da je Sun u oktobru 1997. zbog toga tužio Microsoft, na kraju Microsoft isplatio Sun-u 20 miliona dolara i obustavio razvoj u domenu Java virtuelnih mašina. Da je, hipotetski, Microsoft zadržao entuzijazam za Javom — da li bi posle još uopšte bilo .NET-a?

Na kraju da progovorimo i o: HotSpot VM, podrazumevanoj virtuelnoj mašini za OracleJDK (komercijalni) i OpenJDK (open-source), ujedno i najšire korišćenoj Java virtuelnoj mašini — legendarni prestolonaslednik, prvorođeni sin među Java virtuelnim mašinama.
Tehnička prednost HotSpot-a jeste tehnologija detekcije vrućeg koda (odakle joj i ime) i tehnologija preciznog upravljanja memorijom, mada su se obe već pojavile u Exact VM-u, pa vidiš koliko je važno odabrati dobro ime (šalim se, takva je sudbina).
Detekcija vrućeg koda podrazumeva da se preko brojača izvršavanja pronađe kod koji je najvredniji za kompajliranje, a zatim just-in-time kompajler obavesti, pri čemu se kompajliranje vrši po metodi; interpreter onda više ne mora liniju po liniju da prevodi bajtkod u mašinski kod, već se sve instrukcije bajtkoda cele metode prevode u mašinski kod i tek onda izvršavaju.
Time se efikasnost znatno povećava, zar ne? To je upravo JIT tehnika o kojoj ćemo govoriti kasnije.
Organizaciona arhitektura JVM-a
„A kako izgleda organizaciona arhitektura JVM-a? Od kojih se jedinica sastoji?” — nastavila je Sanmej da ispituje.
JVM se grubo može podeliti u tri odeljenja: učitač klasa (Class Loader), runtime podatkovne oblasti (Runtime Data Areas) i izvršni motor (Execution Engine), kao na slici ispod.

Čime se tačno bave ova tri odeljenja, možeš saznati preko sledeće slike.

Učitač klasa
Učitač klasa jeste odeljenje s najviše ovlašćenja u JVM-u, poput interne kabineta u doba Džang Đuđenga iz dinastije Ming — sve drži u svojim rukama; šta god dvor želi, mora proći kroz mene.
Dakle, učitač klasa služi da učita fajl klase, odnosno .class fajl. Ako učitavanje fajla klase ne uspe, ni runtime podatkovne oblasti ni izvršni motor nemaju šta da rade — ne mogu ništa.
Učitač klasa je odgovoran za učitavanje fajla bajtkoda u memoriju, pri čemu prolazi kroz tri faze: učitavanje -> povezivanje -> inicijalizacija; o tome ćemo govoriti u posebnom poglavlju koje sledi.
Runtime podatkovne oblasti
Runtime podatkovne oblasti su poput državne riznice iz doba dinastije Ming — ako u riznici ima novca, izvršni motor može nastaviti da izvršava bajtkod; ako nema, izbacuje se OutOfMemoryError.
JVM definiše memorijske oblasti potrebne za rad Java programa tokom izvršavanja; jednostavno rečeno, u ovim memorijskim oblastima smeštene su informacije bajtkoda i podaci u toku izvršavanja programa, a sakupljač smeća takođe obavlja recikliranje objekata upravo nad runtime podatkovnim oblastima. Pogledaj sliku i biće ti jasno (specifikacija JVM-a):

Runtime podatkovne oblasti obično obuhvataju pet delova: oblast metoda, heap, virtuelni mašinski stek, stek native metoda i brojač programa. Ipak, podela runtime podatkovnih oblasti se menjala kroz razvoj JDK-a; JDK 1.6, JDK 1.7 i JDK 1.8 imaju različitu podelu memorije.

O tome ćemo govoriti u posebnom poglavlju koje sledi.
Izvršni motor
Izvršni motor (Execution Engine) je poput Šest ministarstava iz dinastije Ming; uglavnom obavlja konkretne poslove. „Virtuelna mašina” jeste pojam naspram „fizičke mašine”; obe mašine imaju sposobnost izvršavanja koda, pri čemu je razlika u tome što je izvršni motor fizičke mašine izgrađen direktno na nivou procesora, keša, skupa instrukcija i operativnog sistema, dok je izvršni motor virtuelne mašine sopstvena softverska implementacija, pa stoga nije ograničen fizičkim uslovima u prilagođavanju odnosa između skupa instrukcija i strukture izvršnog motora, te može izvršavati i one formate skupa instrukcija koje hardver ne podržava neposredno.
Zadatak izvršnog motora jeste da instrukcije bajtkoda interpretira/kompajlira u lokalne mašinske instrukcije odgovarajuće platforme. Jednostavno rečeno, izvršni motor u JVM-u jeste prevodilac koji prevede viši jezik u jezik mašine.

- Interpretator: čita bajtkod, a zatim izvršava instrukcije. Pošto instrukcije interpretira i izvršava liniju po liniju, brzo interpretira bajtkod, ali je samo izvršavanje sporije (jer se jedna linija izvrši pa sledeća).
- Just-in-time kompajler: izvršni motor najpre radi u režimu interpretiranog izvršavanja, a s vremenom just-in-time kompajler selektivno deo vrućeg koda kompiluje u lokalni kod. Izvršavanje lokalnog koda je znatno brže od interpretiranog izvršavanja instrukciju po instrukciju, jer se lokalni kod čuva u kešu.
- Sakupljač smeća, koji sakuplja smeće-među objektima u heap memoriji.
O svemu tome ćemo detaljno govoriti u poglavljima koja slede.
Kratak pregled
„Sanmej, o temi šta je JVM zaustavićemo se ovde; detalje ćemo razraditi kasnije, šta kažeš?” — rekao sam joj, okrećući ukočeni vrat. „JVM je velika i duboka tema; ako te odmah na početku preopteretim, bojim se da ću te obeshrabriti.”
„Dobro, Erge, i mislim da je za danas dovoljno znanja — moram da ga nekoliko dana svarim. Ali daću sve od sebe!” — Sanmej je izgledala kao da je puna nade za budućnost, a to je upravo ono što sam želeo da vidim.
Ukratko, JVM jeste okruženje za izvršavanje Java programa; ono krije složenost ispodležećeg operativnog sistema i hardvera i pruža ujedinjenu, stabilnu i bezbednu platformu za izvršavanje.

Predamo mu fajl bajtkoda dobijen kompajliranjem Java izvornog koda i on se može izvršavati u JVM-u — bilo da je kompajliran pod Windowsom, Linuxom ili MacOS-om, svuda može da radi, čime se kriju razlike ispodležećeg operativnog sistema.
