M A S A R Y K O V A U N I V E R Z I T A F A K U L T A I N F O R M A T I K Y CACAO: alternativní virtuální stroj Javy B A K A L Á Ř S K Á P R Á C E Ondřej Pražák Brno, 2013 Prohlášení Prohlašuji, že tato bakalářská práce je mým původním autorským dílem, které jsem vypracoval samostatně. Všechny zdroje, prameny a literaturu, které jsem při vypracování používal nebo z nich čerpal, v práci řádně cituji s uvedením úplného odkazu na příslušný zdroj. Vedoucí práce: Mgr. Marek Grác ii Poděkování Rád bych poděkoval Mgr. Markovi Grácovi za odborné vedení mé práce. Mé díky také patří Ing. Pavlovi Tišnovskému, Ph.D. za vedení mé práce po technické stránce, obětavou pomoc při praktické části této práce a zapůjčenou výpočetní techniku. V neposlední řadě děkuji mým rodičům a všem, kteří mě ve studiu podporovali. iii Shrnutí Cílem této práce je představit prvky implementace virtuálních strojů Java HotSpot a C A C A O V M , navhnout a následně vytvořit sadu jednoduchých testů a s jejich využitím porovnat výkonnost jednotlivých strojů. Celkem bylo vytvořeno pět testů založených především na manipulaci s objekty a číselných operacích. HotSpot Server dosahoval jednoznačně nejvyšší výkonosti ve všech testech. Výkonnost strojů HotSpot Client a C A C A O se na základě provedených testů ukazuje jako více ovlivnitelná typem prováděné úlohy. iv Abstract The goal of this thesis is to describe implementation elements of Java HotSpot and C A C A O virtual machines, design and create a set of simple performance tests and evaluate performance of aforementioned virtual machines with the use of created tests. Five tests were created, which are based on object manipulation and numeric operations. HotSpot Server achieved best performance in all tests. Based on the results of performed tests, performance of HotSpot Client and C A C A O appears to be more influenced by the type of task. v Klíčová slova Java, virtuální stroj, C A C A O , HotSpot, JVM, JIT, výkonnostní testy vi Obsah Úvod 2 1 Význam virtuálních strojů 3 1.1 Historický kontext 3 1.2 Vlastnosti a klasifikace virtuálních strojů 4 2 Technologie Java 7 2.1 Programovací jazyk Java 8 2.2 Application-programming interface 9 2.3 Virtuální stroj Javy 9 3 HotSpot V M 16 4 CACAO V M 20 5 Porovnání výkonnosti virtuálních strojů 24 5.1 Test RychlostMnoziny 24 5.2 Test Collections 26 5.3 Test Connect 28 5.4 Test Bubble 29 5.5 Test PrimeSieve 31 5.6 Hodnocení výsledků testů 33 Závěr 36 Literatura 37 Index 40 A Obsah CD 42 1 Úvod Od svého vzniku v roce 1995 se technologie Java stala jednou z nejrozšířenějších vývojových platforem dnešní doby. Podle údajů společnosti Oracle využívalo v roce 2011 tuto technologii více než 9 milionů vývojářů a více jak 3 miliardy přístrojů [23]. Rozsáhlá dokumentace a zkušenosti nasbírané komunitou za více než 15 let poskytují bohaté zdroje informací nejen pro vývojáře, ale také pro potenciální zájemce o výzkum a využití stávajících vlastností platformy v nových směrech a oblastech. Reimplementace virtuálního stroje Javy (JVM, Java Virtual Machine) patří do jedné z experimentálních oblastí vývoje a výzkumu díky otevřené specifikaci JVM , která má pouze rámcový charakter a nesnaží se klást restriktivní podmínky na případné tvůrce JVM, nýbrž je explicitně vyzývá k hledání nových postupů a implementací. Jednou z alternativních implementací JVM je C A C A O V M , jenž je předmětem zájmu této bakalářské práce. Hlavními úkoly je popsat vlastnosti virtuálních strojů HotSpot a C A C A O , vytvořit sadu jednoduchých testů a na základě výsledků zhodnotit výkonnost výše zmíněných virtuálních strojů. Kapitola 1 krátce shrnuje vývoj virtuálních strojů a jejich obecné vlastnosti. Kapitola 2 představuje jednotlivé součásti technologie Java. Kapitola 3 se věnuje implemenatci virtuálního stroje HotSpot. Kapitola 4 představuje virtuální stroj C A C A O . V kapitole 5 jsou popsány jednotlivé testy společně s dosaženými výsledky. 2 Kapitola 1 Význam virtuálních strojů 1.1 Historický kontext Termín virtuální stroj (virtual machine, V M ) byl poprvé použit firmou IBM v roce 1959 při popisu jejich průkopnického systému [17, s. 8]. Základní myšlenkou bylo vytvoření přechodného stavu uvnitř kompilátoru programovacího jazyka, který by využil frontend a back-end ke vzájemné komunikaci. Jazykově závislý front-end by provedl sémantickou kontrolu a kompilaci do přechodného stavu, který by následně převzal kód generující back-end. V ideálním případě by byl front-end nezávislý na cílovém hardwaru, stejně jako back-end na zdrojovém programovacím jazyku, ve kterém by byl program napsán [12]. Během šedesátých let byl koncept virtuálních strojů podrobněji rozpracován [26] a v sedmdesátých letech se objevila první implementace virtuálního stroje, která vytvářela abstrakci hardwaru pro vývoj v jazyku SmallTalk [17, s. 8]. Využití virtuálního stroje pro kompilaci jednotlivých metod do nativního strojového kódu mělo za cíl zrychlit překlad programů. Tato implementace následně ovlivnila množství systémů, SmallTalkem inspirovaný jazyk SELF vyžadoval sofistikované řešení funkce kompilátoru, protože jeho interpret pracuje v porovnání s interpretem SmallTalku ještě pomaleji. Dva vývojáři, kteří se podíleli na vývoji virtuálního stroje pro SELF, založili v roce 1994 společnost Animorphic Systems se sídlem v Palo Alto. Zde došlo k upravení dřívější implementace stroje pro SELF, především se jednalo o vylepšení správy paměti a rychlosti kompilátoru. Původní záměr byl nasadit tuto technologii v nové implementaci pro SmallTalk. Vzrůstající popularita jazyka Java od roku 1995 se odrazila také v činnosti společnosti Animorphic systems, která využila dosavadní zkušenosti k vlastní implementaci virtuálního stroje Javy (Java Virtual Machine, JVM). V roce 1997 převzala společnost Sun Microsystems kontrolu nad Animorphic Systems [7, s. 123]. 20. dubna 2009 se Sun Microsystems stalo součástí firmy Oracle [5]. 3 1. V Ý Z N A M V I R T U Á L N Í C H STROJU 1.2 Vlastnosti a klasifikace virtuálních strojů Základní myšlenkou pro realizaci virtuálních strojů je vytvořit pomocí abstrakce několik rozdílných prostředí, a tak dosáhnout iluze, že každé z těchto prostředí je zcela nezávislé na ostatních [28, s. 64]. Virtualizace využívá abstrakci k mapování rozhraní virtuálního stroje na rozhraní a zdroje níže se nacházejícího reálného systému, čímž reálný systém získá podobu jednoho či více virtuálních systémů, přičemž tyto virtuální systémy mohou mít zcela odlišné vlastnosti. Abstrakce poskytovaná virtuálním strojem zajišťuje eliminaci reálných vlivů nižších vrstev, čímž je zajištěna kompatibilita softwaru běžícím na virtuálním stroji. Jedinou podmínkou pro zachování kompatibility je úspěšné namapování rozhraní virtuálního stroje na rozhraní nižší vrstvy. Software zodpovědný za řízení virtuálního stroje (monitor VM) je schopný spravovat požadavky na hardwarové zdroje jednotlivých strojů implementovaných na jednom systému takovým způsobem, že dosahuje jejich naprosté izolace. Vysokou záruku dokonalé izolace jednotlivých V M zajišťuje relativně malá část kódu. Libovolný kód spuštěný na jednom z V M tak nemůže vstoupit do ostatních V M ani do monitoru. Oddělení jednotlivých V M na jednom fyzickém systému je zcela srovnatelné se dvěma fyzicky oddělenými systémy. Zapouzdření (encapsulation) je vlastnost, která umožňuje monitoru V M spravovat veškerý software virtuálního stroje jako jeden celek a zajišťuje transparentní funkcionalitu softwarových komponent. Díky této vlastnosti lze jednoduše přenášet virtuální stroje mezi jednotlivými platformami. Praktické využití nacházejí virtuální stroje při přechodu uživatelů na novější verzi dosavadního operačního systému nebo na zcela jiný systém, který nemusí podporovat všechny aplikace, které byly zcela kompatibilní s jeho předchůdcem. Zachování úplné zpětné kompatibility je řešeno virtualizací, kdy na jednom fyzickém stroji běží zároveň starý i nový systém. Vlastnosti izolace lze úspěšně využít k segregaci přístupu k datům z jednoho fyzického stroje. Vytvořením dvou virtuálních strojů, z nichž jeden bude mít přístup výhradně do privátní a druhý výhradně do veřejné sítě, získá uživatel ochranu dat dostupných z privátní sítě před útoky přicházejícími ze sítě veřejné. Možnost přístupu k množství nezávislých prostředí s různými vlastnostmi je výhodou při vývoji a testování softwaru. Vyvíjený produkt lze jednoduše otestovat v rozdílných prostředích s odlišným nastavením, takto lze také zajistit prostředí pro testování zpětné kompatibility [26]. 4 1. V Ý Z N A M V I R T U Á L N Í C H STROJU Přestože virtuální stroje disponují řadou užitečných vlastností, jejich implementace je náročná. Každý z implementovaných virtuálních strojů požaduje výhradní přístup ke zdrojům reálného systému, což klade zvýšené nároky na plánování činnosti C P U a správu paměti. Virtualizační vrstva přidává na komplexitě celého systému, neboť virtuální stroj operuje v uživatelském a privilegovaném režimu (user mode, kernel mode) uvnitř uživatelského režimu hostujícího stroje. Akce, které vyvolají změnu z uživatelského režimu do privilegovaného na reálném stroji musí způsobit totéž ve virtuálním stroji. Při systémovém volání ve virtuálním stroji získá kontrolu monitor V M , který pozastaví virtuální stroj a deleguje požadavek na reálný systém. Po provedení požadavku reálným systémem promítne monitor změny do registrů a PC (Program Counter) virtuálního stroje a znovu ho spustí. Simulace privilegovaných operací virtuálního stroje zabírá více času, než kdyby tyto operace byly prováděny přímo v reálném systému, navíc při využití multiprogramování mezi větším množstvím virtuálních strojů může docházet k nepředvídatelnému zpomalování jednotlivých strojů [28, s. 64-67]. Software vytváří virtualizační vrstvu na různých místech reálného systému a podle jejího umístění můžeme provést následující klasifikaci [29], která je graficky znázorněna na obrázku 1.1: • Virtualizace systému. Virtualizační vrstva se nachází přímo nad hardwarem reálného systému a veškerý software tohoto systému poběží na virtuálním stroji. Toto je původní definice virtuálního stroje z šedesátých let minulého století. Tato implementace poskytuje perzistentní prostředí, které podporuje operační systém s uživatelskými procesy. • Virtualizace procesu. Virtualizační vrstva se nachází mezi operačním systémem a aplikační vrstvou. Jedná se o virtuální platformu, která vykonává individuální proces. Je vytvořena, když je vytvořen proces a zaniká s jeho ukončením. Podmnožinou druhé skupiny jsou virtuální stroje programovacích jazyků vysoké úrovně (high-level language, HLL). Implementace těchto strojů umisťuje virtualizační vrstvu nad operační systém hostujícího stroje a z jeho pohledu je virtuální stroj považován za jeden z aplikačních programů [26]. Platformové nezávislosti H L L je dosaženo zahrnutím virtuálního stroje do jeho vývojového prostředí. Odpovídající V M neodpovídá žádné z existujících platforem, je navrhnut s ohledem na jednoduchou přenositelnost a specifické aspekty H L L , pro který je vytvořen. U konvenčního, platformně závislého H L L nejprve kompilátor vytvoří kód podobný strojovému kódu, ze kterého je vytvořen binární soubor obsahující strojový kód pro 5 1. V Ý Z N A M V I R T U Á L N Í C H STROJU Guest Runtime • Host (a) Guest VMM Host (b) Application process Virtualizing software OS Hardware Applications OS Virtualizing software ruTJTJTj~Lnj~LrLn_n Hardware Application process Process virtua machine Applications OS System virtual machine Obrázek 1.1: a: Virtualizace procesu, b: Virtualizace systému [29]. specifický operační systém a instrukční sadu (instruction set architecture, ISA). Vytvořený soubor může být distribuován a spouštěn na platformách se shodnou kombinací operačního systému a instrukční sady. U H L L V M vytvoří kompilátor abstraktní strojový kód, který je specifikován rozhraním V M . Abstraktní kód je distribuován ke spuštění na různých platformách. Každá hostující platforma implementuje V M , který je schopný načtení a spuštění abstraktního kódu. Nejjednodušší forma V M obsahuje interpret, sofistikovanější kompilují abstraktní kód do strojového kódu pro přímé spuštění na hostující platformě. Výhodou H L L V M je jednoduchost portování aplikací, jakmile jsou příslušné knihovny a V M implementovány na hostujícím stroji [29]. Technologii V M využívá platforma Java a podrobněji o ní pojednává následující kapitola. 6 Kapitola 2 Technologie Java Java je technologie zavedená firmou Sun Microsystems v průběhu 90. let 20. století. Java je označována jako technologie, neboť zahrnuje více než samotný programovací jazyk. Třemi základními komponentami jsou [28, s. 67]: • Specifikace programovacího jazyka Java • Rozhraní pro programování aplikací (Application-programming interface, API) • Specifikace virtuálního stroje Javy (JVM) Java API a J V M společně tvoří platformu Java. Grafická reprezentace platformy Java SE 7 se nachází na obrázku 2.1. J a v a L a n g u a g e Java Language Tools Si Java javac javadoc apt jar Java p J PDA jconsole Tool APIs Security Infi RMI IDL Deploy Monitoring Troufoleshoot Scripting JVM Tl D e p l o y m e n t T e c h n o l o g i e s Deployment Java Web Start Java Plug-in U s e r Interface AWT Swing Java 2D Tool kits Accessibility Drag n Drop Input Methods Image I/O Print Sen/ice Sound Integration Libraries IDL JDBC ' JNDI RMI RMI-IIOP Scripting Other Base Beans Intl Support I/O JMX JMI Math Libraries Networking Override Mechanism Security Serialization Extension Mechanism XML JAXP lang and util Collections Concurrency Utilities g Management lang and Jtil lang and util Collections Concurrency Utilities JAR Loggir g Management Base L i b r a r i e s Preferences API Ref Objects Reflection Regular Expressions Versioning Zip Instrument J a v a Vi rtual Machine Java Hotspot17 C Java Hotepoť7 SerrerVM Platforms Solaris'" Linux Windows Other J a v a SE API Obrázek 2.1: Platforma Java SE 7 [21]. 7 2. T E C H N O L O G I E J A V A 2.1 Programovací jazyk Java Java je objektově orientovaný programovací jazyk vysoké úrovně. Mezi jeho vlastnosti patří podpora programování více vláken, nezávislost na platformě či architektuře, podpora distribuovaných aplikací, snadná osvojitelnost, silná a statická typovanost, bez­ pečnost. Jazyk Java je navržen pro rychlé osvojení programátory, jeho vývoj byl ovlivněn jazykem C/C++, avšak oproti tomuto jazyku jsou některé aspekty Javy odlišné kvůli důrazu na produktivitu vývoje aplikací. Neexistují zde příkazy pro preprocesor (direktiva #def ine, klíčové slovo t y p e d e f v C / C++), čímž je odstraněna závislost na znalosti kontextu kódu. Struktury a uniony lze nahradit deklarací třídy s vhodnými instančními proměnnými. V Javě neexistují funkce, jejich plnohodnotným ekvivalentem jsou metody třídy. Vícenásobná dědičnost v Javě není podporována, požadovaná funkcionalita je zajišťována pomocí dědičnosti od jednoho předka a implementací rozhraní. K přehlednosti kódu přispívá eliminace příkazu goto, který bývá často zneužíván. Nejsou podporovány automatické koerce, pretypovaní musí být vždy explicitní. S eliminací struktur a přítomností tříd A r r a y a S t r i n g neexistuje potřeba poinetrů. Jejich eliminace zvyšuje kvalitu kódu, neboť při manipulaci s pointery dochází velmi často k chybám [10]. Požadavky na přenositelnost, nezávislost na platformě a distribuovatelnost jsou důležité s ohledem na uplatnění webových aplikací. Rozšíření Javy bylo spojováno s podporou appletů [17]. Silná a statická typovanost poskytuje rozlišení mezi compile-time errors (chybami během kompilace) a run-time errors (chybami za běhu). Kompilace sestává z překladu programů z jazyka Java (soubory s příponou . j ava) do strojového kódu JVM (soubory s příponou . c l a s s), známého též jako bytecode. Aktivity za běhu zahrnují načtení a linking tříd potřebných ke spuštění programu, dynamickou optimalizaci programu a jeho vlastní spuštění [11, s. 1]. Soubor c l a s s přesně definuje reprezentaci třídy nebo rozhraní včetně základních parametrů, které mouhou být nastaveny implicitně na odlišné hodnoty u různých platforem, jeho přesnou strukturu popisuje Java Virtual Machine Specification [16, s. 69 -74]. Vysoká úroveň jazyka Java se projevuje vlastnostmi JVM, které nejsou pomocí jazyka přímo dosažitelné. Tyto vlastnosti zahrnují například automatickou správu paměti, typicky používající garbage collector jako nástroj k ochraně před problémy způsobenými explicitní dealokací (f ree v C a d e l e t e v C++) [11, s. 1]. 8 2. T E C H N O L O G I E J A V A Java podporuje vícevláknové aplikace již na úrovni jazyka, kde poskytuje základní nástroje pro synchronizaci vláken prostřednictvím třídy Thread. Systémové knihovny byly navrženy thread-safe, což znamená, že poskytovaná funkcionalita je dostupná bez konfliktu vláken při souběžném běhu [10]. 2.2 Application-programming interface Java API obsahuje tři hlavní položky [28, s. 68-69]: • Java Standard Edition (SE) - standardní API pro návrh desktopových aplikací a appletů se základní podporou grafiky, 1/O, bezpečnosti, přístupu k databázím a síťových služeb. Poskytuje také podporu pro řešní v oblasti vestavěných systémů (etnbedded environment). • Java Enterprise Edition (EE) - podnikové API pro návrh serverových aplikací s podporou pro databáze • Java Micro Edition (ME) - API pro návrh aplikací určených pro zařízení menších rozměrů, například mobilních telefonů. 2.3 Virtuální stroj Javy Ochrana před některými druhy běhových chyb a portabilita programů napsaných v Javě jsou důležité vlastnosti, ve skutečnosti však nejsou zajišťovány jazykem Java ale virtuálním strojem Javy [13]. Virtuální stroj Javy je abstraktní stroj, který má, stejně jako stroj reálný, sadu instrukcí pro manipulaci s obsahem paměťových adres. Korektní implementace J V M je schopná načíst c l a s s soubory a správně vykonávat v nich uvedené instrukce [16, s. 5]. Hlavními částmi J V M jsou class loader a interpret, který může být u sofistikovanějších implementací nahrazen just-in-time (JIT) kompilátorem. Class loader načte c l a s s soubory programu a požadované soubory Java API, které jsou předány interpretu k vykonání. Instance J V M je vytvořena při každém spuštění Java aplikace nebo appletu, začíná svůj běh, když je volána metoda main [28, 69-70]. JVM definuje datové oblasti, které jsou používány za běhu programu. Některé jsou vytvářeny při startu JVM a zanikají s jeho ukončením, jiné vznikají při vytvoření vlákna a zanikají s jeho ukončením. Každé vytvořené vlákno má svůj privátní p c (program counter) a zásobník, do kterého jsou vkládány rámce (frames). Zásobník vláken je analogický zásobníku v jazyku C, obsahuje lokální proměnné, částečné výsledky a podílí se na 9 2. T E C H N O L O G I E J A V A volání metod. Paměť vyhrazená zásobníku nemusí být souvislá, což umožňuje jeho dynamické zvětšení při zvýšených výpočetních nárocích. Každý rámec obsahuje lokální proměnné a operand stack, může být rozšířen o data specifická pro danou implementaci. Lokální proměnné se uchovávají v poli indexovaném od nuly, jehož délka se určuje při kompilaci. Lokální proměnná může obsahovat hodnotu typu boolean, byte, s h o r t , char, i n t , f l o a t , r e f e r e n c e nebo returnAddress. Dvojice po sobě jdoucích proměnných může obsahovat hodnoty typu l o n g nebo double, hodnota je adresována nižším z indexů. J V M využívá lokální proměnné rámců k předání parametrů při volání metod [16, s. 15-16]. Každý rámec obsahuje last-in-first-out (LIFO) zásobník označovaný jako operand stack, který s instrukcemi pro operace nad zásobníkem zajišťuje prováděcí mechanismus JVM. Ukázka 2.1 demonstruje vložení dvou celočíselných hodnot na zásobník, jejich sečtení a uložení výsledku do lokální proměnné. Ukázka 2.1: Sčítání na zásobníku JVM [12] 1 i l o a d a // vlož na zásobník proměnnou a 2 i l o a d b // vlož na zásobník proměnnou b 3 iadd // sečti dva horní elementy, vlož výsledek i i s t o r e c // odstraň horní element a ulož do proměnné c JVM má k dispozici haldu Qieap), která je sdílena mezi všemi vlákny. Jedná se o datovou oblast, kde je za běhu alokována paměť pro instance tříd. Halda je vytvořena při startu JVM. Oblasti haldy zabírané již neodkazovanými objekty běžící aplikace nejsou explicitně dealokovány, ale jsou uvolněny pomocí systému pro automatickou správu, který je známý jako garbage collector [16, s. 11-15]. Garbage collector není specifikací explicitně vyžadován, jediným požadavkem je přítomnost správy haldy, proto implementace s pevnou velikostí haldy, která při vyčerpání kapacity vyhodí výjimku OutO fMemory splňuje požadavky specifikace. Garbage collector a detaily jeho implementace jsou ponechány zcela v kompetenci vývojářů JVM [32, kapitola 9 - Garbage Collection]. Správa paměti má za úkol bezchybně rozpoznat, kdy alokované objekty již nejsou potřebné, dealokovat paměť zabíranou takovými objekty a zpřístupnit ji pro následné alokace nových objektů. Objekty nejsou potřebné, pokud na ně již neexistuje odkaz. Jedním z rizik při explicitní správě paměti je dealokace objektu, který je stále odkazován. Místo původního objektu je poté přiřazeno objektu novému a při pokusu o přístup k původnímu objektu pomocí jeho odkazu získáme jiný zde umístěný objekt, což může vést k nepředvídatelným výsledkům. Další problém při explicitní správě 10 2. T E C H N O L O G I E J A V A paměti je znám jako memory leak. V tomto případě není alokovaná paměť odkazována, ale nedojde k její dealokaci. Pokud nastane velký počet memory leaks, může dojít k úplnému vyčerpání paměti. Mezi hlavní požadavky na garbage collector patří také efektivnost. Dostatečná bezpečnost musí zaručit, že odkazovaná data nebudou dealokována a neodkazovaná data nebudou v paměti přetrvávat déle, než malé množství cyklů sběru. Jedním z cílů je také malá fragmentace. Po odstranění objektů se volné místo může nacházet v malých nesouvislých oblastech, nedostatečně velkých pro alokaci většího objektu. Tento problém řeší setřásání objektů (compaction). Při implementaci garbage collector algoritmů je nutno mít přehled o výhodách a nevýhodách jednotlivých postupů. Paralelní garbage collector je oproti sériovému schopen rozdělit úlohu mezi více C P U a paralelně provézt sběr v rychlejším čase za cenu případné fragmentace a vyšší komplexity prováděných úkonů. Garbage collection může probíhat současně s aplikací (Concurrent garbage collection), alternativně lze použít přístup Stop-the-world, kdy je celá aplikace pozastavena, avšak pro některé aplikace může být pozastavení jejich běhu nežádoucí. Přístup Stop-the-world je jednodušší, nebof se objekty v haldě během sběru nemění. Také Concurrent collection nemusí probíhat zcela paralelně s aplikací a může vyžadovat její krátké pozastavení, navíc je třeba zvýšené opatrnosti, protože se pracuje s měnícími se objekty aplikace. Concurrent collection se přednostně používá pro větší kapacity hald. Po odstranění nepotřebných objektů může proběhnout setřásání perzistujících objektů, jehož výsledkem jsou souvislé oblasti volné paměti, což urychluje alokaci nových objektů oproti haldě, kde k setřásání nedochází. Setřásání vyžaduje dodatečné zdroje a prodlužuje dobu potřebnou pro garbage collection. Další alternativou je překopírování živých objektů do jiné oblasti paměti [30]. Method area je oblastí sdílenou všemi vlákny J V M a jedná se o analogii úložiště pro zkompilovaný kód konvenčních programovacích jazyků. Obsahuje data třídních metod, kód metod a konstruktorů, včetně metod používaných při inicializaci instancí tříd a inicializaci rozhraní. Method area se vytváří při stratu JVM. Přestože logicky tvoří součást haldy, její umístění, stejně jako ostatní detaily implementace, je přenecháno kreativitě tvůrců JVM [16, s. 13-14]. JVM při startu vytváří implementačně závislou iniciální třídu a inicializační metodu v o i d main (St r i n g [ ] ), jejíž průběh může způsobit volání dalších metod stejně jako načítání dalších tříd a rozhraní [16, s. 338]. Za dynamické načítání softwarových komponent zodpovídají class loaders. Jedná se o instance podtříd abstraktní třídy C l a s s Loader. Soubory c l a s s obsahují symbolické odkazy na jiné třídy a metody. V ukázce 2.2 obsahuje c l a s s soubor reprezentující třídu C symbolický odkaz na třídu D. Aby mohl být symbolický odkaz na třídu D vyřešen, musí být nejprve načten příslušný 11 2. T E C H N O L O G I E J A V A c l as s soubor a vytvořen typ třídy D . Vyřešení odkazu na třídu D vyžaduje také vyřešení všech nadtříd této třídy [1]. Ukázka 2.2: Odkaz na jinou třídu [1] 1 class C { 2 void foo () { 3 D d = new D(); 4 } 5 / / další kód třídy 6 } Třída C l a s s L o a d e r obsahuje metodu de f i n e C l a s s , která je finál, a tak nemůže být překryta žádnou z podtříd. Metoda def i n e C l a s s bere jako argument c l a s s soubor a vrací nově vytvořený objekt třídy, v případě neplatného formátu nebo poškozeného c l a s s souboru je vyhozena výjimka. Pokud je vyvolána metoda def i n e C l a s s a vrátí objekt, potom je příslušný class loader označován jako defining loader výsledné třídy [24]. Předpokládejme, že třída C z ukázky 2.2 byla načtena pomocí L. Pak L je defining loader třídy C a JVM bude využívat L k načítání tříd odkazovaných z C [1]. Metoda l o a d C l a s s třídy C l a s s L o a d e r bere jako argument jméno třídy ve formě řetězce a vrátí objekt, nebo vyhodí výjimku. Uživatelem definovaný kód této metody může implementovat rozdílné způsoby načítání tříd, obvykle načte c l a s s soubor a vyvolá metodu d e f i n e C l a s s , které předá právě načtený soubor jako argument. Kód v těle metody l o a d C l a s s může také delegovat načítání na jiný class loader [24]. Při delegaci jeden class loader inicializuje načítání pomocí metody l o a d C l a s s a jiný definuje třídu metodou d e f i n e C l a s s . Uvažujme, že načítání třídy C z ukázky 2.2 bylo inicializováno pomocí L, který deleguje načítání na M. Potom L je initiating loader a M je defining loader třídy C. V případě, že vytváříme vlastní class loader, doporučuje se dodržovat následující body pro zachování bezpečnosti: • Pokud existuje balík, ze kterého class loader není oprávněn načítat třídy, dojde ke kontrole, zda vyžadovaná třída nenáleží do tohoto balíku. V případě, že třída náleží do balíku se zákazem čtení, je vyhozena výjimka, jinak se pokračuje následujícím bodem. 12 2. T E C H N O L O G I E J A V A • Uživatelsky definovaný class loader deleguje požadavek na předka (systémový class loader), který buď vrátí požadovanou třídu, nebo celý proces pokračuje následujícím krokem. • Pokud existuje balík, do kterého není náš class loader oprávněn přidávat třídy, kontroluje se, zda požadovaná třída nenáleží do takového balíku. Pokud ano, je vyhozena výjimka, jinak se pokračuje následujícím krokem. • Nakonec se class loader pokusí načíst třídu ad hoc, například pomocí přístupu k síti. Při úspěchu je je vrácena požadovaná třída, jinak je vyhozena výjimka. První bod zajišťuje, že není načtena třída z nedůvěryhodných zdrojů, třetí bod chrání před umístěním nedůvěryhodné třídy do důvěryhodného balíku [32, kapitola 3 - Secu- rity]. Delegování dovoluje oddělení jmených prostorů při současném přístupu k jedné množině tříd. Třída C načtená v prvním appletu je považována za odlišnou od třídy C načtené v druhém appletu, neboť k jejich načtení byly použity rozdílné class loaders. Přestože třídy disponují shodnými jmény, jejich obsah může být naprosto odlišný. Class loaders appletu delegují všechny systémové třídy na systémový class loader, což zajišťuje sdílení všech systémových tříd mezi applety a unikátnost typů systémových tříd, jako například j a v a . l a n g . St r i n g . Ukázka 2.3: Porušení typové bezpečnosti [1] class C{ void foo() { Spoofed x = Delegated.goo (); } } class Delegated{ Spoofed goo(){ // kód metody } } Metoda l o a d C l a s s může pro jedno jméno třídy vrátit různé typy tříd. K zajištění typové bezpečnosti musí JVM vždy získat stejný typ třídy pro stejné jméno a class loader. 13 2. T E C H N O L O G I E J A V A Protože JVM nemůže věřit uživatelsky definované metodě l o a d C l a s s , že konzistatně vrátí stejný typ pro stejné jméno, uchovává vnitřně loaded class cache, která mapuje jméno třídy a initiating loader na typ třídy Pro vyhledávání v loaded class cache slouží metoda f i n d L o a d e d C l a s s . Při delegaci může za jistých okolností dojít k porušení typové bezpečnosti. Uvažme, že v ukázce 2.3 je L defining loader třídy Spoof ed a M je defining loader třídy Delegated. Třída C je definována pomocí L. Důsledkem toho L inicializuje načítání tříd Spoof ed a D e l e g a t e d odkazovaných v metodě fo o. Protože M je defining loader třídy Delegated, deleguje L načítání této třídy na M. Třída D e l e g a t e d tak využije právě M k inicializaci načítání odkazované třídy Spoof ed při volání D e l e g a t e d . goo. V případě, že existuje třída Spoof ed definovaná pomocí M, dojde k typové chybě, neboť C očekává instanci Spoof ed delegované pomocí L, ale místo toho dostane instanci Spoof ed delegovanou pomocí M, což je instance zcela jiné třídy se shodným názvem [1]. Řešením problému typové bezpečnosti je nepovolovat identická jména tříd, efektivnějším řešením je zahrnout do typu defining class loader společně se jménem třídy a za běhu kontrolovat typovou ekvivalenci [27]. Alternativně ke kontrole typové ekvivalence se nabízí zavedení množiny podmínek, které jsou dynamicky aktualizovány a kontrolovány [1]. Další významnou fází v běhu JVM je linking zahrnující verifikaci (verification) a přípravu (preparation) třídy nebo rozhraní a jejich přímých předků. Volitelně zde může být zahrnuto vyřešení (resolution) symbolických odkazů [16, s. 345]. Verifikace zajišťuje, že operace probíhají na správných typech dat. Ověřuje se, že načítané třídy jsou ve správném formátu a nepoškozené. Specifikace J V M poskytuje flexibilitu v implementaci, kvůli zvýšení výkonu je však množství kontrol prováděno staticky v rámci verifikace [24]. Dochází ke kontrole korektních deklarací metod, ověřuje se, že metody s modifikátorem přístupu finál nejsou překryty a taktéž třídy označené jako finál nemají potomky. Nejobtížnější částí je bytecode verifikace. J V M musí ověřit bytecode integritu pro každou volanou metodu. Bytecode verifikace může být implementována za běhu těsně před vykonáním jednotlivých instrukcí, ale implementace obecně usiluje o souběžnou verifikaci bytecode proudů s využitím dataflow analysis, což pozitivně ovlivňuje rychlost programů napsaných v Javě [32, kapitola 3 - Security]. Dataflow analysis probíhá nezávisle na každé metodě. Kontrolují se správnosti argumentů instrukcí, hlídají se přetečení i podtečení vyhodnocovacího zásobníku a věnuje se pozornost správné inicializaci objektů, neboť k jejich vytvoření dochází ve více krocích. Nejdříve je alokováno místo v paměti a instrukce, která tuto akci vyvolala, vrací odkaz na toto nově alokované místo. Poté je inicializován objekt voláním jednoho z konstruktem třídy. Konstruktor zodpovídá za korektní vytvoření objektu. Až do dokončení 14 2. T E C H N O L O G I E J A V A inicializace konstruktorem je stav objektu nedefinovaný a jeho chování může být nekonzistentní. Sémantika jazyka nedovoluje používání nově vytvořených objektů před dokončením jejich inicializace a vynutit dodržování tohoto pravidla je úkol pro bytecode verifier, což je jedna z hlavních komponent bezpečnostní architektury. Bytecode verifier musí také zajistit skutečnost, že neinicializovaný objekt musí být inicializován kostruktorem deklarovaným v třídě objektu a nikoliv konstruktorem z jiné třídy. Mezi další požadavky patří, že objekt nesmí být inicializovaný vícekrát než jednou a v případě, že při inicializaci je vyhozena výjimka, objekt nesmí být použit, neboť jeho inicializace není kompletní [8]. Po provedení verifikace probíhá fáze přípravy, kdy J V M alokuje místo pro třídní proměnné a nastaví je na iniciální hodnoty příslušící jejich typu. Následuje nepovinné vyřešní symbolických odkazů a po něm inicializace, která nastavuje třídní proměnné na jejich řádné hodnoty. Inicializace musí začínat vždy až po úplném dokonční fáze přípravy. Inicializace třídy nebo rozhraní probíhá ve dvou krocích. Nejprve se inicializuje nadtřída, pokud ještě není inicializována, a poté se volá inicializační metoda třídy [32, kapitola 7 - The Lifetime of the Class]. Virtuální stroj se ukončuje, když některé vlákno volá metody e x i t nebo h a l t třídy Runtime, stejně tak při volání metody e x i t třídy System. Volání těchto metod musí být v daném okamžiku povoleno [16, s. 360]. 15 Kapitola 3 HotSpot V M Java HotSpot V M je implemenatací virtuálního stroje Javy firmou Sun Microsystems pro technologii Java a tvoří součást platformy Java SE. Tato platforma obsahuje dvě implementace Java V M , které využívají rozdílné kompilátory: • Java HotSpot Client V M . Virtuální stroj optimalizovaný pro běh aplikací v prostředí klienta, hlavními atributy jsou snížené požadavky na paměť a nižší doba při startu. Jedná se o vylepšený virtuální stroj a JIT kompilátor používaný v předchozích verzích. • Java HotSpot Server V M . Virtuální stroj navržený pro dlouhodobě běžící serverové aplikace, důraz je kladen především na rychlost prováděných operací. Distribuce JDK obsahuje oba systémy, explicitní výběr lze provést uvedením hodnoty - c l i e n t nebo - s e r v e r [20]. Při spuštění HotSpot V M dojde k parsování voleb z příkazové řádky a podle nalezené volby - c l i e n t nebo - s e r v e r dojde k načtení příslušných knihoven. Následně je určena velikost haldy, zvolen typ kompilátoru a vytvořeny proměnné prostředí. Poté se vytvoří V M v novém vlákně voláním JNI.Creat e JavaVM. Jakmile dojde k vytvoření a inicializování V M , je načtena třída obsahující metodu main, která je volána s parametry z příkazové řádky pomocí C a l l S t a t i c VoidMethod. Po dokončení metody main je nutné odstranit všechny nezachycené výjimky metodou Except i o n O c c u r e d a předat návratovou hodnotu volajícímu procesu. Odstranění vlákna je provedeno vykonáním DetachCurrentThread, dekrementuje se celkový počet vláken, a zavolá se De s t roy JavaVM. Za načítání tříd zodpovídá HotSpot V M společně s knihovnami Java SE. Pro jméno třídy nebo rozhraní se nalezne příslušný c l a s s soubor a vytvoří se objekt typu j a v a . l a n g . Class. V případě, že nelze nalézt binární reprezentaci dané třídy dojde k chybě NoClassDefFound. Pokud nelze rozpoznat formát souboru, vznikají chyby C l a s s F o r m a t E r r o r nebo U n s u p p o r t e d C l a s s V e r s i o n E r r o r v závislosti na druhu po- 16 3. H O T S P O T V M škození. Když je třída svou vlastní nadtřídou, vytváří se chyba C l a s s C i r c u l a r i t y E r r o r1 . Následná verifikace provádí sémantickou a typovou kontrolu, která může vyhodit V e r i f y E r r o r . Fáze přípravy probíhá zcela shodně s principy popsanými v sekci 2.3. HotSpot V M využívá líný postup při linkování pro dosažení vyššího výkonu. Pokud se třída A odkazuje na třídu B, načtení třídy A spustí načítání třídy B pouze v případě, že to vyžaduje fáze verifikace. V opačném případě se začne třída B načítat v okamžiku, kdy dojde ke spuštění první instrukce, která se na ni odkazuje. Jméno třídy nebo rozhraní je definováno jakofully qualified name, které zahrnuje jméno balíku (package name). HotSpot V M udržuje tři hašovací tabulky, které obsahují informace o načítání tříd. SystemD i c t i o n a r y obsahuje jména načtených tříd společně a jejich inicializační a definující loader. P l a c e h o l d e r T a b l e uchovává informace o právě načítaných třídách. LoaderC o n s t r a i n t T a b l e udržuje podmínky pro kontrolu typové bezpečnosti. Class data sharing je vlastnost, která se snaží snížit čas potřebný ke startu aplikací. Při instalaci JRE dojde k načtení množiny systémových tříd a jejich umístění do jednoho souboru. Během následujících volání JVM je tento soubor mapován do permanentní generace paměti. Třídy obsažené v souboru proto nemusí být načítány, což má za následek úsporu paměti. Class data sharing vykazuje nejlepší výsledky pro menší aplikace, je podporován pouze pro Java HotSpot Client V M a sériový garbage collector. HotSpot generuje interpret při startu pomocí třídy I n t e r p r e t G e n e r a t o r s použitím informací z tabulky Temp l a t e Table, která obsahuje popis jednotlivých bytecode instrukcí. Vysoká rychlost interpretu je vykoupena velkými oblastmi strojově závislého kódu. Celková komplexita kódu je navíc zvýšena podporou pro dynamické generování kódu, což znesnadňuje debugging a implementaci HotSpot V M . Interpret je důležitou součástí optimalizační strategie, která eliminuje některé nevýhody JIT kompilátoru. Výchozím poznatkem je skutečnost, že téměř všechny aplikace stráví většinu času vykonáváním malého množství kódu. Java HotSpot V M spouští program pomocí interpretu, za běhu analyzuje kód a snaží se detekovat důležitá místa (hot spots) v programu. Poté dochází k optimalizaci pomocí kompilace nalezených hot spots. Zbytečnému zvýšení celkového času kompilace se předchází vynechámím kompilace nepoužívaných částí kódu. Hledání důležitých částí programu pokračuje dynamicky, program se za běhu přizpůsobuje požadavkům uživatele na výkon jednotlivých částí [20]. HotSpot V M využívá pro garbage collection techniku generational collection, kdy je paměť rozdělena do generací - oddělených oblastí obsahujících objekty odlišného stáří. 1. Obecný průběh načítání tříd podrobněji popsán v části 2.3 17 3. H O T S P O T V M V každé generaci může být uplatněn rozdílný garbage collection algoritmus optimalizovaný pro danou generaci. Mezi dva základní poznatky, na kterých je tato implementace založena, patří pozorování, že většina nově vytvořených objektů není odkazovaná dlouhou dobu a existuje pouze málo odkazů ze starší generace do mladší. HotSpot organizuje paměť do tří generací - mladé, staré a permanentní. Většina nově alokovaných objektů se nachází v mladé generaci. Stará generace obsahuje přemístěné objekty z mladé generace, které přežily několik sběrů a některé velké objekty, které mohou být alokovány přímo ve staré generaci. Permanentní generace obsahuje objekty, u kterých je považováno za vhodné, aby je garbage collector spravoval. Jakmile se naplní mladá generace, proběhne garbage collection pouze u této generace. V případě naplnění staré a permanentní generace se spustí garbage collection u všech tří generací. HotSpot ve verzi Java SE 5.0 zahrnoval čtyři různé garbage collectors. Při použití sériového kolektoru jsou generace sesbírány sériově za využití jednoho CPU. V době sběru je aplikace pozastavena, jedná se o přístup stop-the-world. Sběr v mladé generaci využívá rozdělení této generace na Eden a dvě survivor spaces. Živé objekty jsou z Edenu zkopírovány do jednoho ze survivor spaces, které bylo při začátku sběru prázdné (označeno jako To na obrázku 3.1) s výjimkou objektů, které jsou příliš velké, ty se přesouvají do staré generace. Také objekty z původně obsazeného survivor space (označeno jako Front na obrázku 3.1), které jsou relativně mladé, se přesouvají do To, relativně staré objekty se přesouvají do staré generace. Po přesunutí objektů se všechny objekty, které nebyly přesunuty považují za mrtvé. Po proběhnutí garbage collection jsou Eden a původně zaplněné survivor space prázdní, survivor spaces si prohazují úlohu, jak je znázorněno na obrázku 3.2. Young Generation Eden From To \ X X Old Obrázek 3.1: Sériový sběr mladé generace - začátek [30]. 18 3. H O T S P O T V M Young Generation empty Eden To From empty • a Survivor Spaces Old Generation O C Z Z 3 0 Obrázek 3.2: Sériový sběr mladé generace - konec [30]. Paralelní kolektor byl vyvinut s ohledem na využití víceprocesorových systémů. Stejně jako sériový kolektor využívá stop-the-world mechanismus, avšak využití více procesorů zkracuje dobu pozastavení aplikace. Parallel Compacting Collector je vylepšeným nástupcem paralelního kolektoru, který eliminuje fragmentaci starší generace. Concurrent Mark-Sweep Collector je zaměřen na snížení délek stop-the-world pozastavení aplikací, u kterých je kladen důraz na rychlou odezvu. C M S collector provádí značnou část sběru staré generace za běhu aplikace [30]. V Java SE 6 HotSpot nahradil Parallel Compacting Collector zcela paralelní kolektor [22]. Pro JDK 7 update 4 a následující verze je dostupný Garbage-First Collector, který je zamýšlen jako náhrada pro C M S collector. Jedná se o paralelní concurrent garbage collector určený především pro servery a velké haldy. Mezi hlavní výhody patří efektivní setřásání objektů a dobře předpovídatelné stop-the-world pauzy [19]. 19 Kapitola 4 CACAO V M C A C A O je virtuální stroj navržený v roce 1996 v Institut für Computersprachen der Technischen Universität Wien. Primárním záměrem bylo vytvořit JVM s rychlou kompilací a vykonáním kódu. C A C A O používá pouze JIT kompilátor, který kompiluje metodu do nativního kódu, když je metoda volána. První implementace C A C A O V M byla provedena pro 64-bitovou RISC (Reduced Instruction Set Computer) architekturu Alpha. Vývoj byl v roce 1999 pozastaven, v roce 2002 se vývojářský tým rozhodl implementovat C A C A O pro platformy IA32 a AMD64. Následovaly úpravy, které měly za cíl splnit podmínky JVM specifikace a zveřejnit C A C A O pod G N U General Public Licence [31, s. 6-7]. V současné době je k dispozici verze 1.6 podporující architektury arm, i386, powerpc, powerpc64, x86_64 [6]. Architektura RISC procesorů je zcela jiná, než zásobníkový model, který používá Java V M . RISC procesory mají velké množství registrů a vykonávají pouze opearace nad hodnotami umístěnými v registrech. Lokální proměnné metod jsou obvykle umístěny v registrech a do poměti se ukládají pouze v případě nedostatečného počtu registrů [15]. Alpha má 32 celočíselných registrů a 32 registrů s pohyblivou čárkou, registry obou skupin mají šířku 64 bitů. Architektura CISC (Complex Instruction Set Computer) mají menší počet registrů, IA32 vlastní 8 a AMD64 16 celočíselných registrů pro všeobecné účely. Menší počet registruje kompenzován bohatší instrukční sadou [31, s. 31-33]. C A C A O v původní implementaci pro architekturu Alpha provádí překlad do strojového kódu v několika fázích. Nejprve se identifikují skokové příkazy a jejich cíle, které rozdělují kód do bloků. V další fázi jsou jednotlivé bloky vcelku procházeny a pro každý je vytvořena reprezentace v přechodném kódu. Do pseudoregistrů jsou umístěny lokální proměnné a přechodné hodnoty, které mohou například sloužit jako argumenty funkcí. V případě, že jsou do pseudoregistrů umístěny argumenty funkcí, mají tyto pseudoregistry životnost po dobu průběhu metody. Pokud jsou do pseudoregistrů umístěny operandy JVM zásobníku, pak mají pseudoregistry krátkou životnost. Zda se pro 20 4. C A C A O V M daný pseudoregistr použije CPU registr se rozhodne v pozdější fázi alokace registrů [14, s. 30-33]. Alokátor registruje zodpovědný za přiřazování registrů pro pseudoregistry. Protože kód je generován za běhu, z důvodu rychlosti nelze použít náročné algoritmy jako například obarvování grafu. S přihlédnutím k této skutečnosti je implementován algoritmus, který přiřazuje registry sekvenčně podle výskytu pseudoregistrů v kódu. V případě nedostatku registrů je využita paměť (register spilling), k čemuž však nedochází v nadměrné míře a proto je tato implementace dostatečně efektivní pro architekturu Alpha [14, s. 41-45]. Pro CISC architekturu se plánuje implementace nového mechanismu alokace registrů založeného na linear scan algoritmu [31, s. 38]. Cílem je nahradit J V M zásobník pomocí přístupu k pseudoregistrům. Postupným vykonáváním instrukcí je nahlíženo do pseudoregistrů, které obsahují odpovídající hodnoty J V M zásobníku. V závislosti na sémantice jsou pseudoregistry na zásobník přidávány nebo odebírány [14, s. 33]. Překlad do nativního kódu transformuje každý J V M příkaz l o a d a s t o r e s využitím instrukce MOVE, což generuje velké množství MOVE instrukcí. Z toho důvodu je přistoupeno k optimalizaci, která zaznamenává do tabulky, které registry obsahují stejnou hodnotu. Když je dosaženo konce bloku, instrukce MOVE je generována pro všechny registry v tabulce. Výraz a = b * c + d v JVM kódu (ukázka 4.1) bude přeložen do přechodného kódu uvedeného v ukázce 4.2. Instrukce i l o a d b negeneruje instrukci MOVE pro přesun lokální proměnné b do registru 10, což je položka na JVM zásobníku. Pouze se zaznamená, že registry b a tO mají stejný obsah. Podobně dojde k záznamu ekvivalence obsahu 11 a c při provedení instrukce i l o a d c. Tímto způsobem je docíleno odstranění MOVE instrukcí [15]. Po provedení všech přípravných a optimalizačních fází nepředstavuje vytvoření odpovídajícího strojového kódu náročný problém [14, s. 46]. Ukázka 4.1: a = b * c + d v JVM kódu [15] 3 imul 2 i l o a d c i i l o a d b // načti proměnnou b // načti proměnnou c // b * c i i l o a d d 5 iadd // načti proměnnou d //b * c + d 6 i s t o r e a // ulož vrchol zásobníku do a 21 4. C A C A O V M Ukázka 4.2: a = b * c + d v přechodném kódu [15] i 0P2(IMUL) b, c, t2 ; tO ==b, t l == c 2 OP2(IADD) t 2 , d, a ; t 3 == d, 14 == a C A C A O používá JIT kompilátor, proto jsou při spuštění V M v tabulkách metod pouze ukazatele na stubs, jejichž jediným úkolem je spustit kompilátor a zajistit překlad dané metody. Následně se aktualizují pouze ukazatele na přeloženou metodu, které byly skutečně použity [14, s. 55-56]. V původní implementaci C A C A O využívalo eager class loading, tj. při načtení třídy se okamžitě načítaly další třídy z ní odkazované [14, s. 57]. Lazy class loading byl implementován později ve snaze přiblížit C A C A O specifikaci JVM [31, s. 21]. Linking zajišťuje vytváření stubs a inicializace nastává při prvním případu active use, tj. při prvním volání třídní metody nebo přístupu ke třídní proměnné [14, s. 57]. Garbage collector (GC) v původní implementaci pro architekturu Alpha byl mark-andsweep s konzervativním přístupem k pointerům. Halda byla rozdělena na 8B bloky a každý blok obsahoval 3 bity s dodatečnými informacemi. S-bit je nastaven u bloků, kde začíná nový objekt nebo volné místo. M-bit ukazuje, že daný objekt je odkazovaný. Během značkovací fáze jsou nejprve všechny M-bity smazány. Postupným procházením odkazů se zjišťuje, které objekty jsou dosažitelné. U dosažitelných objektů se nastaví M-bit, konec objektu je označen následujícím S-bitem, tudíž i volné bloky musí mít nastavený S-bit. Sweep fáze aktualizuje seznam volných bloků, konec volného bloku je označován S-bitem následujícího obsazeného bloku. Třetí bit obsahuje informaci, zda objekt v daném bloku vůbec může obsahovat odkaz na jiný objekt. Pokud je tento bit nastaven, dochází k přesunu k následujícímu S-bitu bez dalšího čtení dat v příslušném objektu [14, s. 58-64]. V současné době probíhají práce na novém G C [9]. Virtuální stroj C A C A O byl díky své malé velikosti experimentálně využito pro embedded systémy, přestože pro prostředí s omezenými zdroji a nejsou technologie J V M příliš vhodnou variantou. C A C A O V M spoléhá na operační systém při správě vláken a I/O operací, což vyžaduje dodatečné zdroje, a proto byla implementována knihovna umožňující spouštět programy bez podpory operačního systému. Další nutnou změnou v této implementaci byl odlišný přístup ke kompilaci, neboť JIT kompilace nedokáže zaručit včasnost požadovaných operací nutnou pro embedded systémy operující v omezených časových podmínkách. JIT kompilace byla nahrazena selektivní kompilací metod během inicializace V M (ahead-of-time kompilace), kdy může docházet k neome- 22 4. C A C A O V M zenému načítání tříd bez hrozby kolize s vykonáním kriticky důležitých úloh. Celkovým efektem modifikací byly potlačeny dynamické vlastnosti platformy jako trade-off za včasnost prováděných operací a nenáročnost na zdroje, což jsou kritické požadavky embedded systémů [2]. 23 Kapitola 5 Porovnání výkonnosti virtuálních strojů Výkonnostní testování bylo provedeno na dvou testovacích strojích. První stroj disponoval 7,9 GB R A M a čtyřjádrovým procesorem Intel Xeon 3.07 Ghz, jako operační systém byla zvolena Fedora 14, 32bit. Druhý stroj měl k dispozici 7,9 GB R A M a čtyřjádrový procesor Intel Xeon 1,6 Ghz, testy byly prováděny pod operačním systémem Fedora 18,64bit. C A C A O verze 1.6 bylo nainstalováno s využitím G N U classpath na obou strojích, jak je uvedeno v oficiálních instrukcích [25]. Použitá Java verze byla 1.6.0. u prvního stroje, 1.7ul7 u stroje druhého s cílem využít při testování novějšího SW. Celkem bylo spuštěno pět testů, jejichž zdrojový kód je dostupný na přiloženém C D společně s naměřenými hodnotami v jednotlivých bězích testů. Každý test byl spuštěn a měřen padesátkrát po sobě. Hodnoty jsou udávány v milisekundách, pokud není uvedeno jinak. N a prvním stroji jsou porovnávány C A C A O V M , HotSpot Client, HotSpot Server a HotSpot Client i Server v interpretovaném módu. U druhého stroje nebylo možné provést srovnání s HotSpot Client, neboť pro 64 bitové verze je podporován pouze HotSpot Server. 5.1 Test RychlostMnoziny Tento test vznikl mírnou modifikací zdrojového kódu, který byl použit pro porovnání HotSpot client a HotSpot server [18]. Jeho podstatou je měření času, za který se naplní kolekce HashSet objekty typu Integer. N a prvním stroji si nejrychleji vedl v tomto testu HotSpot Server, po něm následovaly HotSpot Client a C A C A O . HotSpot Server i Client v interpretovaném módu (-Xint) dosahovaly výrazně horších výsledků. Údaje popisné statistiky zobrazuje tabulka 5.1. Obrázek 5.1 znázorňuje průměrné rychlosti jednotlivých virtuálních strojů při tomto testu pro první stroj. Na druhém stroji si nejrychleji počínal HotSpot Server, po něm C A C A O a nejpomaleji si vedl HotSpot při interpretaci kódu. Popisná statistika se nachází v tabulce 5.2, průměrné rychlosti zobrazuje graf 5.2. 24 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ C A C A O client client -Xint server server -Xint průměr 53,7 38,44 204,82 13,3 165,74 medián 53 37 203 13 166 sm. odchylka 4,53 7,41 6,15 3,20 2,54 1. kvartil 52 36 202 11 165 3. kvartil 53 38 206 16 167 kvart, rozptyl 1 2 4 5 2 Tabulka 5.1: Popisná statistika testu RychlostMnoziny, stroj 1 server -Xint • server client -Xint • client • cacao 1 1 1 1 1 0 50 100 150 200 250 Obrázek 5.1: Průměrné rychlosti při testu RychlostMnoziny, stroj 1 C A C A O server server -Xint průměr 44,6 12,96 319,98 medián 43 12 320 sm. odchylka 5,07 3,33 3,59 1. kvartil 43 11 318 3. kvartil 44 14 322 kvart, rozptyl 1 3 4 Tabulka 5.2: Popisná statistika testu RychlostMnoziny, stroj 2 25 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ server-Xint • server • cacao 0 50 100 150 200 250 300 350 Obrázek 5.2: Průměrné rychlosti při testu RychlostMnoziny, stroj 2 5.2 Test Collections Při tomto testu se plnila kolekce HashSet kolekcemi HashSet, které obsahovaly objekty typu Integer. N a prvním stroji byl nejrychlejší HotSpot Server, po něm následují C A C A O a HotSpot Client. HotSpot Server i Client při interpretaci kódu jsou v tomto testu nejpomalejší. Hodnoty popisné statistiky se nacházejí v tabulce 5.3. Obrázek 5.3 ukazuje graf průměrných rychlostí virtuálních strojů. Pořadí průměrných hodnot je u druhého stroje shodné jako v předchozím testu na první pozici HotSpot, po něm C A C A O a na poslední pozici HotSpot v režimu interpretace kódu. Popisnou statistiku obsahuje tabulka 5.4, graf průměrných hodnot je na obrázku 5.4. C A C A O client client -Xint server server -Xint průměr 103,22 116,62 1932,68 70,56 1353,1 medián 103 117 1927 70 1394 sm. odchylka 0,50 0,56 15,32 1,69 7,78 1. kvartil 103 116 1925 70 1348 3. kvartil 103 117 1932 71 1360 kvart, rozptyl 0 1 7 1 12 Tabulka 5.3: Popisná statistika testu Collections, stroj 1 26 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ server -Xint • server client -Xint • client • cacao T 1 1 1 1 1 0 500 1000 1500 2000 2500 Obrázek 5.3: Průměrné rychlosti při testu Collections, stroj 1 C A C A O server server -Xint průměr 80,82 54,92 2213,66 medián 81 54 2220 sm. odchylka 0,65 3,21 20,26 1. kvartil 80 53 2212 3. kvartil 81 55 2222 kvart, rozptyl 1 2 10 Tabulka 5.4: Popisná statistika testu Collections, stroj 2 27 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ 5.3 Test Connect Tento test je založen na opakovaném spojování řetězců (objektů typu S t r i n g ) . Nejlepších průměrných výsledku na prvním stroji dosáhl HotSpot Server při interpretaci kódu a tentýž V M ve standartním režimu, po nich C A C A O , jak je vyjádřeno v grafu na obrázku 5.5. Tabulka 5.5 uvádí hodnoty popisné statistiky pro tento test. Na druhém stroji byl HotSpot v průměru rychlejší než C A C A O , a to i při interpretaci kódu. Popisná statistika pro výsledky dosažené na druhém stroji v tomto testu se nachází v tabulce 5.6 a obrázek 5.6 ukazuje graf průměrných rychlostí. C A C A O client client -Xint server server -Xint průměr 644,06 678,70 821,84 429,08 420 medián 624 683 868 424,5 413,5 sm. odchylka 60,81 25,61 114,55 18,01 19,48 1. kvartil 608 680 865 421 412 3. kvartil 663 685 874 435 425 kvart, rozptyl 55 5 9 14 13 Tabulka 5.5: Popisná statistika testu Connect, stroj 1 28 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ C A C A O server server -Xint průměr 904,42 437,82 748,84 medián 926 434 749 sm. odchylka 97,14 21,26 3,21 1. kvartil 919 432 747 3. kvartil 938 438 751 kvart, rozptyl 19 6 4 Tabulka 5.6: Popisná statistika testu Connect, stroj 2 server-Xint • server • cacao 0 200 400 600 800 1000 Obrázek 5.6: Průměrné rychlosti při testu Connect, stroj 2 5.4 TestBubble Předchozí testy byly zaměřeny hlavně na práci s objekty, zatímco následující zkoumají především rychlost číselných operací. Tento test měří čas, za který proběhne vzestupné seřazení pole čísel typu i n t algoritmem Bubble sort. Nejrychleji si na prvním stroji vedl HotSpot Server, který byl následován stroji HotSpot Client a C A C A O . Interpretace kódu u strojů HotSpot byla časově mnohonásobně delší. Tabulka 5.7 obsahuje hodnoty popisné statistiky pro tento test, graf průměrných rychlostí je k vidění na obrázku 5.7. Na druhém stroji dosahoval v průměru nejrychlejších výsledků HotSpot Server, po něm C A C A O a HotSpot v režimu interpretace kódu. Hodnoty popisné statistiky jsou obsaženy v tabulce 5.8, obrázek 5.8 ukazuje graf průměrných rychlostí. 29 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ C A C A O client client -Xint server server -Xint průměr 201,42 110,86 1422,2 38,28 1456,32 medián 201,5 110 1422 36 1457 sm. odchylka 0,7 3,02 0,57 12,01 2,4 1. kvartil 201 110 1422 36 1454 3. kvartil 202 111 1423 36 1458 kvart, rozptyl 1 1 1 0 4 Tabulka 5.7: Popisná statistika testu Bubble, stroj 1 C A C A O server server -Xint průměr 176,9 39,9 1553,5 medián 175,5 37 1553 sm. odchylka 2,52 15,04 20,17 1. kvartil 175 36 1540 3. kvartil 180 37 1559 kvart, rozptyl 5 1 19 Tabulka 5.8: Popisná statistika testu Bubble, stroj 2 30 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ server-Xint • server • cacao 0,0 500,0 1000,0 1500,0 2000,0 Obrázek 5.8: Průměrné rychlosti při testu Bubble, stroj 2 5.5 Test PrimeSieve Tento test vyhledává počet prvočísel od nuly po stanovenou horní hranici pomocí algoritmu Eratosthenova síta. Pořadí průměrných výsledků prvního stroje je velmi podobné pořadí výsledků u předchozího testu, jediným rozdílem je rychlejší interpretace kódu u HotSpot Server v porovnání s HotSpot Client. Hodnoty popisné statistiky se nacházejí v tabulce 5.9. Graf 5.9 znázorňuje průměrné rychlosti testu jednotlivých virtuálních strojů. U druhého stroje je pořadí identické jako u předchozího testu, nejrychlejší je v průměru HotSpot, následují C A C A O a HotSpot při interpretaci kódu. Tabulka 5.10 obsahuje hodnoty popisné statistiky, obrázek 5.10 ukazuje graf průměrných rychlostí. C A C A O client client -Xint server server -Xint průměr 725,46 378,78 2114,76 310,06 2093,12 medián 724 379 2112 309,5 2095 sm. odchylka 4,44 0,83 15 2,22 13,83 1. kvartil 723 378 2112 309 2093 3. kvartil 727 379 2112 311 2100 kvart, rozptyl 4 1 0 2 7 Tabulka 5.9: Popisná statistika testu PrimeSieve, stroj 1 31 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ server -Xint • server client -Xint • client • cacao 1 1 1 1 1 0 500 1000 1500 2000 2500 Obrázek 5.9: Průměrné rychlosti při testu PrimeSieve, stroj 1 C A C A O server server -Xint průměr 716,94 308,4 2464,160 medián 715 307,5 2464,5 sm. odchylka 8,34 8,58 8,41 1. kvartil 713 304 2459 3. kvartil 722 314 2468 kvart, rozptyl 9 10 9 Tabulka 5.10: Popisná statistika testu PrimeSieve, stroj 2 server-Xint • server • cacao 1 1 1 1 1 1 0 500 1000 1500 2000 2500 3000 Obrázek 5.10: Průměrné rychlosti při testu PrimeSieve, stroj 2 32 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ 5.6 Hodnocení výsledků testů Na prvním stroji dosahoval jednoznačně ve všech pěti testech nejlepších výsledků virtuální stroj HotSpot Server. HotSpot Client byl úspěšnější než C A C A O při plnění kolekce HashSet objekty typu Integer, naopak při plnění kolekce HashSet objekty (v tomto případě opět typu HashSet), které obsahují množství jiných objektů (v tomto případě typu Integer) byl úspěšnější virtuální stroj C A C A O . Virtuální stroj C A C A O byl také rychlejší při opakovaném spojování řetězců. V provedených testech se zaměřením na číselné operace projevoval HotSpot Client vyšší rychlost než virtuální stroj C A C A O . HotSpot v režimu interpretace kódu dosahoval vždy horších výsledků v porovnání s C A C A O V M , v případě testu Collections byl více než desetinásobně pomalejší. Výjimkou byl test Connect, kdy HotSpot Server dosáhl při interpretaci kódu překvapivě dobrých výsledků. Na druhém stroji si nejrychleji počínal HotSpot Server ve všech testech, druhé místo obsazoval virtuální stroj C A C A O před strojem HotSpot Server při interpretaci kódu. V testu Connect byl HotSpot v režimu interpretace rychlejší než C A C A O , což je konzistentní s výsledky dosaženými na prvním stroji. Při porovnání výsledků z jednotlivých strojů byly na druhém stroji získány v průměru nižší hodnoty v testech RychlostMnoziny, Collections, PrimeSieve u virtuálních strojů HotSpot Server a C A C A O . V testu Bubble dosáhl C A C A O V M na druhém stroji taktéž nižšího průměrného výsledku než na stroji prvním, pro HotSpot Server platí opak. V testu Connect si HotSpot Server i C A C A O na druhém stroji počínali pomaleji než na stroji prvním. HotSpot Server dosahoval na druhém stroji ve všech testech vyšších průměrných hodnot. Graf 5.11 znázorňuje srovnání relativních výsledků jednotlivých testů pro stroj 1 a graf 5.12 pro stroj 2, výsledný čas virtuálního stroje C A C A O je vždy brán jako 100 %. Tabulka 5.11 ukazuje pořadí virtuálních strojů v jednotlivých testech pro stroj 1 a tabulka 5.13 pro stroj 2. Získané hodnoty pro virtuální stroj C A C A O byly statisticky vyhodnoceny pomocí Mann-Whitney U-testu proti hodnotám všech verzí virtuálního stroje HotSpot. Výsledky těchto testů jsou bez výjimek statisticky významné na hladině p = 0,01 u obou fyzických strojů, na kterých probíhalo testování. Ke statistickému zhodnocení byl zvolen neparametrický test, neboť distribuce získaných hodnot neodpovídá normálnímu rozložení, které je předpokladem pro použití parametrických metod. Jedinou výjimkou je HotSpot při interpretaci kódu v testu RychlostMnoziny na stroji 2, který má rozložení odpovídající normálnímu rozložení na hladině pravděpodobnosti p = 0,05. Aritmetický průměr, který byl použit v grafech jako bodová reprezentace souboru hodnot, může 33 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ 2000 n 1800 - 1600 - 1400 Bubble Collections Connect RychlostMnoziny PrimeSieve Obrázek 5.11: Srovnání relativních výsledků jednotlivých testů, stroj 1 být při absecnci normálnícho rozložení zavádějící, což však neplatí v tomto případě. Většina hodnot se téměř vždy nalézá v úzkém intervalu, což dokazují nízké hodnoty kvartilového rozptylu. Zvýšené hodnoty směrodatných odchylek jsou ovlivněny odlehlými hodnotami, hodnoty mediánů blízké hodnotám odpovídajících průměrů naznačují vhodnost volby průměru jako reprezentativní hodnoty souboru. Histogramy rozložení hodnot pro jednotlivé výkonnostní testy společně s podrobnými hodnotami výpočtů statistických testů jsou součástí elektronické přílohy umístěné na CD. K ověření normálního rozložení dat, výpočtu popisné statistiky a statistických testů byl použit program STATISTICA společnosti StatSoft, verze 10. C A C A O client client -Xint server server -Xint Bubble 3. 2. 4. 1. 5. Collections 2. 3. 5. 1. 4. Connect 3. 4. 5. 2. 1. RychlostMnoziny 3. 2. 5. 1. 4. PrimeSieve 3. 2. 5. 1. 4. Tabulka 5.11: Pořadí virtuálních strojů v jednotlivých testech, stroj 1 34 5. P O R O V N Á N Í V Ý K O N N O S T I V I R T U Á L N Í C H STROJŮ C A C A O server server -Xint Bubble 2. 1. 3. Collections 2. 1. 3. Connect 3. 1. 2. RychlostMnoziny 2. 1. 3. PrimeSieve 2. 1. 3. Obrázek 5.13: Pořadí virtuálních strojů v jednotlivých testech, stroj 2 35 Závěr V této práci byly představeny vybrané prvky implementace virtuálních strojů Java HotSpot a C A C A O . Byla navržena a vytvořena sada pěti testů, na jejichž základě byla porovnána výkonnost výše zmíněných virtuálních strojů. Původní záměr, který dal vzniknout první verzi virtuálního stroje C A C A O v roce 1997, byl vytvořit rychlejší implementaci JVM jako alternativu k tehdejšímu virtuálnímu stroji společnosti Sun, která ve své době využívala pouze interpret kódu [14, s. 2]. Současná verze 1.6 je na základě provedených testů výkonnostně schopná konkurovat virtuálnímu stroji HotSpot Client. Získané výsledky mohou být ovlivněny nastavením při zvolené instalaci virtuálního stroje C A C A O , kde byla využita G N U classpath. Nětkeří autoři však nedosáhli výrazně lepších výsledků při rozdílných nastaveních [4]. Alternativně se nabízí použití OpenJDK a IcedTeaó. Výsledné hodnoty jsou nepochybně ovlivněny typem úlohy vykonávané v jednotlivých testech, jak také naznačují výsledky testu Connect v porovnání s ostatními, z toho důvodu byla snaha vytvořit několik rozdílných testů, které by poskytly objektivní náhled na výkonnost jednotlivých virtuálních strojů. Testováním výkonnosti virtuálních strojů se zabývají také další autoři [3, 4]. Existují také srovnání virtuálních strojů různých technologií [12]. V budoucnu se očekává další vývoj virtuálního stroje C A C A O . Již dnes existuje množství open source implementací J V M (například Kaffe, JamVM), jejich porovnání může přinést zajímavé výsledky. 36 Literatura [1] B R A C H A , G. - L I A N G , S. Dynamic Class Loading in the Java Virtual Machine. In Proc. of the ACM Conf. on Object-Oriented Programming, Systems, Languages and Applications, s. 36-44,1998. Dostupné z: . [2] BRANDNER, F. - THORN, T. - SCHOEBERL, M . Embedded JIT Compilation with C A C A O on YARI. In Proc. of the 12th IEEE International Symposium on Object/Component/Service-Oriented Real-Time Distributed Computing, s. 63-70, 2009. Dostupné z: . [3] Bug Labs. Java VMs Compared [online]. 2008. [cit. 26. 1. 2013]. Dostupné z: . [4] Bug Labs. Java VMs Compared II [online]. 2008. [cit. 26. 1. 2013]. Dostupné z: . [5] BURROWS, P. Oracle Buys Sun [online]. 2009. [cit. 11. 10. 2012]. Dostupné z: . [6] C A C A O V M - Verein zur Forderung der freien virtuellen Maschine C A C A O . CacaoVM [online]. 2012. [cit. 29.11. 2012]. Dostupné z: . [7] DMITRIEV, M . Safe Classes and Data Evolution in Large and Long-Lived Java Applications. Disertační práce, University of Glasgow, 2001. Dostupné z: . [8] D O Y O N , S. - DEBBABI, M . On object initialization in the Java bytecode. Computer Communications. 2000,23, s. 1594-1605. [9] F L A M M E , D. Cacao Wiki [online]. 2012. [cit. 6. 12. 2012]. Dostupné z: . 37 L I T E R A T U R A [10] GOSLING, J. - MCGILTON, H . The Java Language Environment [online]. 1997. [cit. 10. 11. 2012]. Dostupné z: . [11] GOSLING, J. - JOY, B. - STEELE, G. Java Language Specification, Third Edition, 2012. Dostupné z: . [12] G O U G H , K. J. Stacking them up: a comparison of virtual machines. In ACSAC '01: Proc. of the 6th Australasian conference on Computer systems architecture, s. 55-61, 2001. [13] G O U G H , K. J. Parameter Passing for the Java Virtual Machine. In Proc. of the Australasian Computer Science Conference, s. 81-87. Queensland University of Technology, 1998. Dostupné z: < h t t p : / / c i t e s e e r . i s t . p s u . e d u / gough98parameter.html>. [14] GPvAFL, R. C A C A O : Ein 64Bit JavaVM Just-in-time Compiler. Diplomová práce, Technische Universität Wien, 1997. [15] K R A L L , A. - GRAFL, R. C A C A O - A 64 bit JavaVM Just-in-Time Compiler, 1997. Dostupné z: . [16] L I N D H O L M , T. - YELLIN, F. - B R A C H A , G. Java Virtual Machine Specification, Second Edition, 2012. Dostupné z: . [17] MEYER, J. - DOWDING, T. Java Virtual Machine. Cambridge: O'Reilly, 1997. 426 s. ISBN 15-659-2194-1. [18] MIKOLÁŠEK, V. - HEROUT, P. Java HotSpot VM [online]. 2005. [cit. 24. 1. 2013]. Dostupné z: . [19] Oracle. Garbage-First Collector [online]. 2012. [cit. 22. 11. 2012]. Dostupné z: < h t t p : / / d o e s . o r a c l e . c o m / j a v a s e / 7 / d o c s / t e c h n o t e s / g u i d e s / v m / Gl.html>. [20] Oracle. HotSpot Runtime Overview [online]. 15. 8. 2012. [cit. 27. 1. 2013]. Dostupné z: < h t t p : / / o p e n j d k . j a v a . n e t / g r o u p s / h o t s p o t / d o c s / RuntimeOverview.html>. 38 L I T E R A T U R A [21] Oracle. Java SE 7Platform at a Glance [online]. 2012. [cit. 18. 10. 2012]. Dostupné z: . [22] Oracle. Java SE 6 HotSpot Virtual Machine Garbage Collection Tuning [online]. 2012. [cit. 22. 11. 2012]. Dostupné z: . [23] Oracle. Java History Timeline [online]. 2012. [cit. 27.1. 2013]. Dostupné z: . [24] QIAN, Z. - GOLDBERG, A. - COGLIO, A. A Formal Specification of Java Class Loading. In OOPSLA VOProc. of the 15th ACM SIGPLAN conf. on Object-oriented programming, systems, languages, and applications, s. 325-336, 2000. [25] RING, S. Cacao Wiki: Build Recipes [online]. 2012. [cit. 24. 1. 2013]. Dostupné z: < h t t p : / / c l . c o m p l a n g . t u w i e n . a c . a t / c a c a o w i k i / B u i l d R e c i p e s > . [26] ROSENBLUM, M . The Reincarnation of Virtual Machines. Queue - Virtual Machines. 2004, 2, s. 34-40. Dostupné z: . [27] SARASWAT, V. Java is not type-safe, 1997. Dostupné z: . [28] SILBERSCHATZ, A . - GALVIN, P. B. - G A G N E , G. Operating System Concepts with Java. 7td edition. John Wiley & Sons, 2007. 966 s. ISBN 978-047-1769-071. [29] SMITH, J. - NAIR, R. The Architecture of Virtual Machines. Computer (IEEE Computer Society). 2005,38, s. 32-38. [30] Sun Microsystems. Memory Management in the Java HotSpot Virtual M a chine, 2006. Dostupné z: < h t t p : / / j a v a . s u n . c o m / j 2 s e / r e f e r e n c e / whitepapers/memorymanagement_whitepaper.pdf>. [31] THALINGER, C. Optimizing and Porting the C A C A O JVM. Diplomová práce, Technische Universität Wien, 2004. [32] VENNERS, B. Inside Java Virtual Machine. McGraw - Hill, 1997. 39 Index A abstrakce, 4 Alpha, 18,19 Animorphic Systems, 3 B back-end, 3 bytecode, 13 C C/C++, 8 C A C A O , 18,19, 21 CISC, 18 class loader, 9,11 defining, 11 initiating, 12 class loading eager, 20 lazy, 20 CPU, 5 D dědičnost, 8 E encapsulation, 4 F front-end, 3 G garbage collection, 16 garbage collector, 8, 10, 16, linking, 13,16 20 G N U , 18 H halda, 10 hardware, 5 HotSpot, 15,16 client, 15 server, 15 I IBM, 3 interpret, 3 J Java, 7, 9,15 Java API, 7, 9 Java Virtual Machine, 3 JDK, 15 JIT, 9,18,19 JVM, 7,10,13,18,19 K kód abstraktní, 6 strojový, 5 kompilátor, 3, 5, 9 konstruktor, 11,13 L LIFO, 9 M memory leak, 10 method area, 10 monitor V M , 4 O Oracle, 3 platforma, 6 preprocesor, 8 Program Counter, 5, 9 programovací jazyk, 7 proměnná instanční, 8 R režim privilegovaný, 5 uživatelský, 5 RISC, 18 rozhraní, 8,11 S SELF, 3 SmallTalk, 3 software, 5 správa paměti, 5 stroj 40 I N D E X virtuální, 3, 9 Sun Microsystems, 3, 7,15 T třída, 8,11 V virtualizační vrstva, 5 vlákno, 10 V M , 4 Z zásobník, 9,19 zpětná kompatibilita, 4 41 Příloha A Obsah CD • data - složka obsahuje naměřené hodnoty • histograms - složka obsahuje výsledky testu normality dat a reprezentaci naměřených hodnot pomocí histogramů • M W - tato složka obsahuje podrobné hodnoty provedených Mann-Whitney U - testů • tests - v této složce se nacházejí zdrojové soubory jednotlivých testů • descriptive_statistics - zde se nacházejí hodnoty popisné statistiky 42