Virtuální stroj Java - Java virtual machine

Virtuální stroj Java
Návrhář Sun Microsystems
Bity 32bitové
Představeno 1994
Verze 15.0.3
Typ Skládejte a registrujte - zaregistrujte se
Kódování Variabilní
Větvení Porovnávejte a rozvětvujte
Endianness Velký
Otevřeno Ano
Registry
Obecný účel Zásobník operandů na metodu (až 65535 operandů) plus místní proměnné na metodu (až 65535)
Přehled architektury JVM (Java Virtual Machine) na základě specifikace Java SE 7 Specifikace pro virtuální stroj Java

Java Virtual Machine ( JVM ) je virtuální stroj , který umožňuje počítači spouštět Java programy stejně jako programy napsané v jiných jazycích , které jsou sestaveny tak, aby Java bytecode . JVM je podrobně popsán specifikací, která formálně popisuje, co je požadováno v implementaci JVM. Specifikace zajišťuje interoperabilitu programů Java napříč různými implementacemi, takže autoři programů využívající sadu Java Development Kit (JDK) si nemusí dělat starosti s výstřednostmi základní hardwarové platformy.

Implementace referencí JVM je vyvinuta projektem OpenJDK jako otevřený zdrojový kód a obsahuje kompilátor JIT s názvem HotSpot . Komerčně podporované verze Java dostupné od společnosti Oracle Corporation jsou založeny na běhu OpenJDK. Eclipse OpenJ9 je další open source JVM pro OpenJDK.

Specifikace JVM

Virtuální počítač Java je abstraktní (virtuální) počítač definovaný specifikací. Je součástí prostředí Java runtime. Použitý algoritmus shromažďování odpadků a jakákoli interní optimalizace pokynů virtuálního počítače Java (jejich překlad do strojového kódu ) nejsou specifikovány. Hlavním důvodem tohoto opomenutí je zbytečně neomezovat implementátory. Libovolnou aplikaci Java lze spustit pouze v rámci konkrétní implementace abstraktní specifikace virtuálního stroje Java.

Počínaje platformou Java, Standard Edition (J2SE) 5.0, byly změny specifikace JVM vyvinuty v rámci procesu komunity Java jako JSR 924. Od roku 2006 jsou změny specifikace podporující změny navržené ve formátu souboru třídy (JSR 202) probíhá jako vydání údržby JSR 924. Specifikace pro JVM byla publikována jako modrá kniha , Předmluva uvádí:

Máme v úmyslu, aby tato specifikace dostatečně dokumentovala virtuální stroj Java, aby bylo možné provádět kompatibilní implementace čistých prostor. Oracle poskytuje testy, které ověřují správnou funkci implementací Java Virtual Machine.

Jeden z Oracle JVM se jmenuje HotSpot, druhý, zděděný od BEA Systems, je JRockit . Mezi implementace Java do čistých prostor patří Kaffe , OpenJ9 a Skelmir CEE-J . Oracle vlastní ochrannou známku Java a může povolit jeho použití k certifikaci implementačních sad jako plně kompatibilních se specifikací Oracle.

Třídní nakladač

Jednou z organizačních jednotek bajtového kódu JVM je třída . Implementace zavaděče tříd musí být schopna rozpoznat a načíst vše, co odpovídá formátu souboru třídy Java . Jakákoli implementace může kromě souborů třídy rozpoznávat i jiné binární formy , ale musí rozpoznávat soubory tříd .

Zavaděč tříd provádí tři základní činnosti v tomto přísném pořadí:

  1. Načítání: vyhledá a importuje binární data pro typ
  2. Propojení: provádí ověřování, přípravu a (volitelně) řešení
    • Ověření: zajišťuje správnost importovaného typu
    • Příprava: přiděluje paměť pro proměnné třídy a inicializuje paměť na výchozí hodnoty
    • Řešení: transformuje symbolické odkazy z typu na přímé odkazy.
  3. Inicializace: vyvolá kód Java, který inicializuje proměnné třídy na jejich správné počáteční hodnoty.

Obecně existují dva typy třídního zavaděče: zavaděč třídy bootstrap a uživatelem definovaný zavaděč tříd.

Každá implementace virtuálního stroje Java musí mít zavaděč třídy bootstrap, schopný načítat důvěryhodné třídy, a zavaděč tříd rozšíření nebo zavaděč tříd aplikací. Specifikace virtuálního stroje Java neurčuje, jak má zavaděč tříd vyhledávat třídy.

Architektura virtuálního stroje

JVM pracuje na konkrétních typech dat, jak je uvedeno ve specifikacích Java Virtual Machine. Datové typy lze rozdělit na primitivní typy ( celá čísla , plovoucí desetinná čárka, dlouhé atd.) A referenční typy. Dřívější JVM byly pouze 32bitové stroje. longa doubletypy, které jsou 64bitové , jsou podporovány nativně, ale spotřebovávají dvě jednotky úložiště v lokálních proměnných rámce nebo zásobníku operandů, protože každá jednotka je 32 bitů. boolean, byte, short, A chartypy jsou všechny sign-prodloužena (s výjimkou char, což je nula-prodloužil ) a operoval jako 32-bitová celá čísla, stejně jako inttypy. Menší typy mají pouze několik instrukcí pro načítání, ukládání a převod typů specifických pro daný typ. booleanje provozován jako 8bitové bytehodnoty, přičemž 0 představuje falsea 1 představuje true. (I když booleanje tento typ považován za specifikaci od specifikace Java Virtual Machine, druhé vydání tento problém objasnilo, v kompilovaném a spuštěném kódu je malý rozdíl mezi a booleana a, bytekromě manipulace s názvy v signaturách metod a typu booleovských polí. booleanS v signatury metod jsou rozbité, Zzatímco bytes jsou rozbité jako B. Booleovská pole nesou typ, boolean[]ale používají 8 bitů na prvek, a JVM nemá žádnou vestavěnou schopnost sbalit booleany do bitového pole , takže kromě typu, který provádějí a chovají se stejné jako bytepole. Při všech ostatních použitích je booleantyp JVM v podstatě neznámý, protože všechny instrukce k obsluze booleů se používají také k provozu na bytes.) Novější verze JVM (OpenJDK HotSpot JVM) však podporují 64bitové buď mají 32bitový/ 64bitový JVM na 64bitovém OS. Hlavní výhodou spouštění Javy v 64bitovém prostředí je větší adresní prostor. To umožňuje mnohem větší velikost haldy Java a zvýšený maximální počet vláken Java, který je potřebný pro určité druhy velkých aplikací, ale při použití 64bitového JVM ve srovnání s 32bitovým JVM došlo k výkonu.

JVM má hromadu odpadků pro ukládání objektů a polí. Kód, konstanty a další data třídy jsou uložena v „oblasti metod“. Oblast metody je logicky součástí haldy, ale implementace mohou zpracovávat oblast metody odděleně od haldy a například ji nemusí shromažďovat odpadky. Každé vlákno JVM má také svůj vlastní zásobník volání (pro přehlednost se nazývá „zásobník virtuálních počítačů Java“), který ukládá rámce . Při každém volání metody se vytvoří nový rámec a při ukončení této metody se snímek zničí.

Každý rámec poskytuje „zásobník operandů“ a řadu „lokálních proměnných“. Zásobník operandů se používá pro operandy k výpočtům a pro příjem návratové hodnoty volané metody, zatímco lokální proměnné slouží ke stejnému účelu jako registry a slouží také k předávání argumentů metody. JVM je tedy stohovací i registrační stroj .

Bytecode pokyny

JVM má pokyny pro následující skupiny úkolů:

Cílem je binární kompatibilita. Každý konkrétní hostitelský operační systém potřebuje vlastní implementaci JVM a runtime. Tyto JVM interpretují bajtový kód sémanticky stejně, ale skutečná implementace se může lišit. Složitější než pouhá emulace bajtkódu je kompatibilita a efektivní implementace Java jádra API, které musí být namapováno na každý hostitelský operační systém.

Tyto pokyny fungují na souboru společných abstrahované datové typy spíše nativní datové typy jakékoli konkrétní architektury sady instrukcí .

Jazyky JVM

Jazyk JVM je jakýkoli jazyk s funkčností, kterou lze vyjádřit pomocí platného souboru třídy, který může hostovat virtuální počítač Java. Soubor třídy obsahuje pokyny pro virtuální stroj Java ( bajtový kód Java ) a tabulku symbolů a další pomocné informace. Formát souboru třídy je binární formát nezávislý na hardwaru a operačním systému používaný k reprezentaci zkompilovaných tříd a rozhraní.

Existuje několik jazyků JVM, oba staré jazyky přenesené do JVM a zcela nové jazyky. JRuby a Jython jsou možná nejznámějšími porty stávajících jazyků, tj. Ruby a Python . Z nových jazyků, které byly vytvořeny od začátku ke kompilaci do Java bytecode, mohou být nejoblíbenější Clojure , Apache Groovy , Scala a Kotlin . Pozoruhodnou vlastností jazyků JVM je, že jsou navzájem kompatibilní , takže například knihovny Scala lze používat s programy Java a naopak.

Java 7 JVM implementuje JSR 292: Supporting Dynamically Typed Languages on the Java Platform, a new feature which supports dynamically typed languages ​​in the JVM. Tato funkce je vyvinuta v rámci projektu Da Vinci Machine, jehož posláním je rozšířit JVM tak, aby podporoval jiné jazyky než Javu.

Ověřovač bajtů

Základní filozofií Javy je, že je ze své podstaty bezpečné, že žádný uživatelský program nemůže havarovat na hostitelském počítači nebo jiným způsobem nevhodně zasahovat do jiných operací na hostitelském počítači a že je možné chránit určité metody a datové struktury patřící důvěryhodným kód z přístupu nebo poškození nedůvěryhodným kódem prováděným ve stejném JVM. Kromě toho se nesmí vyskytovat běžné chyby programátoru, které často vedly k poškození dat nebo nepředvídatelnému chování, jako je přístup mimo konec pole nebo použití neinicializovaného ukazatele. K zajištění této bezpečnosti se kombinuje několik funkcí Javy, včetně modelu třídy, haldy shromažďované odpadky a ověřovače.

JVM před spuštěním ověří všechny bajtkódy. Toto ověření se skládá především ze tří typů kontrol:

  • Pobočky jsou vždy na platná místa
  • Data jsou vždy inicializována a odkazy jsou vždy bezpečné pro typ
  • Přístup k soukromým nebo balíčkovým soukromým datům a metodám je přísně řízen

První dvě z těchto kontrol probíhají primárně během kroku ověření, ke kterému dochází, když je třída načtena a způsobilá k použití. Třetí se primárně provádí dynamicky, když k datovým položkám nebo metodám třídy poprvé přistupuje jiná třída.

Ověřovatel povoluje pouze některé sekvence bytecode v platných programech, např. Skoková (větev) instrukce může cílit pouze na instrukci v rámci stejné metody . Ověřovatel navíc zajišťuje, že jakákoli daná instrukce funguje na pevném umístění zásobníku, což kompilátoru JIT umožňuje transformovat přístupy do zásobníku na přístupy do pevných registrů. Z toho důvodu, že JVM je architektura zásobníku, neznamená při použití kompilátoru JIT pokutu za rychlost při emulaci v registrových architekturách . Tváří v tvář kódově ověřené architektuře JVM nezáleží na kompilátoru JIT, ať už dostane pojmenované imaginární registry nebo imaginární pozice zásobníku, které musí být přiděleny registrům cílové architektury. Ověření kódu ve skutečnosti odlišuje JVM od klasické stackové architektury, jejíž efektivní emulace s kompilátorem JIT je komplikovanější a obvykle ji provádí pomalejší interpret. Tlumočník používaný ve výchozím nastavení JVM je speciální typ známý jako tlumočník šablon, který převádí bajtkód přímo do nativního strojového jazyka založeného na registru, nikoli jako emulátor zásobníku jako typický tlumočník (V mnoha aspektech lze překladače HotSpot považovat za JIT Compiler spíše než skutečný tlumočník), což znamená, že architektura zásobníku, na kterou se bytecode zaměřuje, není ve skutečnosti použita v implementaci, ale pouze specifikace pro mezilehlou reprezentaci, kterou lze dobře implementovat v architektuře založené na registrech (Další instance zásobníku architektura, která je pouze specifikací a je implementována do virtuálního stroje založeného na registru, je Common Language Runtime).

Původní specifikace ověřovatele bajtkódu používala přirozený jazyk, který byl v některých ohledech neúplný nebo nesprávný. Byla provedena řada pokusů o specifikaci JVM jako formálního systému. Tímto způsobem lze důkladněji analyzovat zabezpečení současných implementací JVM a zabránit potenciálnímu zneužití zabezpečení. Bude -li prokázáno, že spuštěná aplikace je bezpečná, bude také možné optimalizovat JVM přeskočením zbytečných bezpečnostních kontrol.

Zabezpečené spuštění vzdáleného kódu

Architektura virtuálního počítače umožňuje velmi jemnou kontrolu nad akcemi, které kód v počítači smí provádět. Předpokládá, že je kód „sémanticky“ správný, to znamená, že úspěšně prošel procesem (formálního) ověřování bajtkódu, materializovaného nástrojem, případně mimo virtuální počítač. Toto je navrženo tak, aby umožňovalo bezpečné spouštění nedůvěryhodného kódu ze vzdálených zdrojů, model používaný aplety Java a další zabezpečené stahování kódu. Po ověření bytecode se stažený kód spustí v omezeném „ sandboxu “, který je navržen tak, aby chránil uživatele před nesprávným chováním nebo škodlivým kódem. Jako doplněk k procesu ověřování bajtkódu si vydavatelé mohou zakoupit certifikát, pomocí kterého budou digitálně podepisovat aplety jako bezpečné, což jim dává povolení požádat uživatele, aby se vymanil z karantény a přistoupil k místnímu systému souborů, schránce , spouštění externích softwarů nebo síť.

Formální důkaz ověřovatelů bajtových kódů provedl průmysl Javacard (formální vývoj integrovaného ověřovače pro bajtový kód Java Card)

Překladač bytecode a kompilátor just-in-time

Pro každou hardwarovou architekturu je potřeba jiný interpret Java bytecode . Když má počítač překladač bajtových kódů Java, může spustit jakýkoli program bajtového kódu Java a stejný program lze spustit na jakémkoli počítači, který má takový tlumočník.

Když je Java bytecode spuštěn tlumočníkem, bude provádění vždy pomalejší než provádění stejného programu zkompilovaného do nativního strojového jazyka. Tento problém je zmírněn kompilátory JIT (just-in-time) pro provádění Java bytecode. Kompilátor JIT může při provádění programu překládat bajtový kód Java do rodného strojového jazyka. Přeložené části programu pak lze provést mnohem rychleji, než by se dalo interpretovat. Tato technika se aplikuje na často používané části programu. Kompilátor JIT tak může výrazně urychlit celkovou dobu provádění.

Mezi programovacím jazykem Java a bajtovým kódem Java není nutné propojení. Program napsaný v Javě lze zkompilovat přímo do strojového jazyka skutečného počítače a programy napsané v jiných jazycích než v Javě lze zkompilovat do Java bytecode.

Bajtový kód Java má být nezávislý na platformě a bezpečný. Některé implementace JVM neobsahují interpret, ale skládají se pouze z kompilátoru just-in-time.

JVM ve webovém prohlížeči

Na začátku životnosti platformy Java byl JVM prodáván jako webová technologie pro vytváření bohatých webových aplikací . Od roku 2018 se většina webových prohlížečů a operačních systémů, které sdružují webové prohlížeče, nedodává s modulem plug-in Java ani neumožňuje boční načítání jakéhokoli modulu plug-in bez formátu Flash . V JDK 9 byl zastaralý plugin prohlížeče Java .

NPAPI Java prohlížeč plug-in byl navržen tak, aby JVM spustit takzvaný Java applety vložené do HTML stránek. V prohlížečích s nainstalovaným modulem plug-in může aplet kreslit do obdélníkové oblasti na stránce, která je mu přiřazena. Protože modul plug-in obsahuje JVM, aplety Java nejsou omezeny na programovací jazyk Java; v modulu plug-in může běžet jakýkoli jazyk cílený na JVM. Omezená sada rozhraní API umožňuje appletům přístup k mikrofonu uživatele nebo 3D zrychlení, přestože aplety nejsou schopné upravit stránku mimo její obdélníkovou oblast. Adobe Flash Player , hlavní konkurenční technologie, funguje v tomto ohledu stejným způsobem.

V červnu 2015 podle W3Techs klesl počet apletů Java a Silverlight u všech webových stránek na 0,1%, zatímco Flash klesl na 10,8%.

JavaScript JVM a tlumočníci

V květnu 2016 umožňuje JavaPoly uživatelům importovat neupravené knihovny Java a vyvolávat je přímo z JavaScriptu. JavaPoly umožňuje webovým stránkám používat nemodifikované knihovny Java, i když uživatel nemá na svém počítači nainstalovanou Javu.

Kompilace do JavaScriptu

S neustálým zlepšováním rychlosti provádění JavaScriptu v kombinaci se zvýšeným používáním mobilních zařízení, jejichž webové prohlížeče neimplementují podporu pro pluginy, existuje snaha zacílit na tyto uživatele prostřednictvím kompilace do JavaScriptu. Do JavaScriptu je možné buď zkompilovat zdrojový kód, nebo bajtový kód JVM.

Kompilace bytecode JVM, který je univerzální napříč jazyky JVM, umožňuje stavět na existujícím kompilátoru jazyka do bytecode. Hlavními kompilátory JVM bytecode pro JavaScript jsou TeaVM, kompilátor obsažený v Dragome Web SDK, Bck2Brwsr a kompilátoru j2js.

Mezi přední kompilátory z jazyků JVM do JavaScriptu patří kompilátor Java-to-JavaScript obsažený v sadách Google Web Toolkit , Clojurescript (Clojure), GrooScript (Apache Groovy), Scala.js (Scala) a dalších.

Java Runtime Environment

Java Runtime Environment (JRE) vydaný společností Oracle je volně dostupná softwarová distribuce obsahující samostatnou JVM (HotSpot), standardní knihovnu Java ( Java Class Library ), konfigurační nástroj a-až do ukončení v JDK 9-a zásuvný modul prohlížeče. To je nejčastější prostředí Java instalován na osobních počítačích v notebooku a desktop form factor . Mobilní telefony, včetně funkčních telefonů a starších smartphonů dodávaných s JVM, budou s největší pravděpodobností obsahovat JVM určené ke spouštění aplikací cílených na Micro Edition platformy Java. Většina moderních smartphonů, tabletových počítačů a dalších kapesních počítačů, na nichž běží aplikace Java, to s největší pravděpodobností dělá prostřednictvím podpory operačního systému Android , který zahrnuje virtuální počítač s otevřeným zdrojovým kódem nekompatibilní se specifikací JVM. (Místo toho vývojové nástroje Google pro Android berou Java programy jako vstupní a výstupní bajtkód Dalvik , což je nativní vstupní formát pro virtuální počítač na zařízeních Android.)

Výkon

Specifikace JVM poskytuje implementátorům spoustu volného času, pokud jde o podrobnosti implementace. Od Javy 1.3 obsahuje JRE od společnosti Oracle JVM s názvem HotSpot. Byl navržen tak, aby byl vysoce výkonným JVM.

Aby se zrychlilo spuštění kódu, HotSpot spoléhá na kompilaci just-in-time. Ke zrychlení přidělování objektů a shromažďování odpadků používá HotSpot generační hromadu.

Generační hromada

Java Virtual Machine haldy je oblast paměti používaná JVM pro dynamické přidělování paměti .

V HotSpotu je hromada rozdělena do generací :

  • Tyto mladé generace ukládá krátkodobý objekty , které jsou vytvořeny a okamžitě uvolněna.
  • Objekty, které přetrvávají déle, jsou přesunuty do staré generace (nazývané také generace s tenurováním ). Tato paměť je rozdělena do (dvou) prostorů přeživších, kde jsou uloženy objekty, které přežily první a další kolekce odpadků.

Permanentní generace (nebo PermGen ) byl použit pro definici třídy a související metadata před Java 8. trvalé generace nebylo součástí haldy. Permanentní generace byl odstraněn z Javy 8.

Původně neexistovala žádná trvalá generace a objekty a třídy byly uloženy společně ve stejné oblasti. Jelikož ale k vykládce třídy dochází mnohem zřídka než se shromažďují objekty, přesun struktur tříd do určité oblasti umožnil výrazné zlepšení výkonu.

Bezpečnostní

Oracle JRE je nainstalován na velkém počtu počítačů. Koncoví uživatelé s neaktuální verzí JRE jsou proto náchylní k mnoha známým útokům. To vedlo k široce sdílenému přesvědčení, že Java je ze své podstaty nejistá. Od Javy 1.7 obsahuje Oracle JRE pro Windows funkci automatické aktualizace.

Před ukončením modulu plug-in prohlížeče Java mohla každá webová stránka potenciálně spouštět Java applet, který poskytoval snadno přístupný útočný povrch škodlivým webovým stránkám. V roce 2013 společnost Kaspersky Labs uvedla, že modul plug-in Java byl metodou volby pro počítačové zločince. Exploity Java jsou součástí mnoha balíčků exploitů, které hackeři nasazují na napadené webové stránky. Java applety byly odstraněny v Javě 11, vydané 25. září 2018.

Viz také

Reference

externí odkazy