Java Virtual Machine

Die Java Virtual Machine (abgekürzt Java VM oder JVM) ist der Teil der Java-Laufzeitumgebung (Java Runtime Environment, JRE) für Java-Programme, der für die Ausführung des Java-Bytecodes verantwortlich ist. Hierbei wird im Normalfall jedes gestartete Java-Programm in seiner eigenen virtuellen Maschine (VM) ausgeführt. Der andere Teil der Java-Laufzeitumgebung sind die Java-Klassenbibliotheken.

Die JVM dient dabei als Schnittstelle zur Maschine und zum Betriebssystem und ist für die meisten Plattformen verfügbar (z. B. Linux, macOS, Palm OS, Solaris, Windows, z/OS usw.). Die JVM ist meist in den Programmiersprachen C oder C++ geschrieben.

Die Bestandteile der JVM sind
 der Klassenlader (classloader und resolver),
 die Speicherverwaltung und automatische Speicherbereinigung (garbage collection) und die
 Ausführungseinheit (execution engine).

Funktionsprinzip 
Vom Java-Compiler erzeugter (plattformunabhängiger) Bytecode wird von einer plattformabhängigen Java Virtual Machine ausgeführt. Die erzeugten Bytecode-Dateien (Dateiendung „.class“) werden während der Laufzeit in die lokale Maschinensprache übersetzt. Die virtuelle Maschine arbeitet dabei wie ein Interpreter, ist jedoch wesentlich schneller, da z. B. keine Syntaxüberprüfungen mehr vorgenommen werden müssen.

Sicherheitsvorteile 
Die Java Virtual Machine bietet neben der Plattformunabhängigkeit des Bytecodes auch einen Gewinn an Sicherheit. Sie überwacht zur Laufzeit die Ausführung des Programms, verhindert also zum Beispiel Pufferüberläufe, welche zu unvorhersehbarem Verhalten wie etwa dem Absturz des Programmes führen. Im speziellen Fall von Java fällt diese Überwachung sehr einfach aus, da Java nicht direkt Zeiger unterstützt (nur implizit).

Optimierungsverfahren 
Um die Ausführungsgeschwindigkeit (englisch performance) von Java-Programmen zu erhöhen, setzen die meisten Java-VMs sogenannte JIT-Compiler (JITC) ein, die unmittelbar während des Programmablaufs den Bytecode „Just In Time“ („Gerade rechtzeitig“, oder „Gerade zur rechten Zeit“) dauerhaft in Maschinencode übersetzen.
Eine Weiterentwicklung dieses Ansatzes ist der Hotspot-Optimizer von Sun, welcher mit dynamischer Optimierung arbeitet.

Dynamische Optimierung 

Oft ist zum Zeitpunkt der Kompilierung nicht bekannt, welche konkrete Eingabe eine Software verarbeiten muss. Demzufolge muss die Software mit allen Arten von Eingaben zurechtkommen. Die Eingabe wird demnach in Variablen gespeichert. Nach dem Start des Programms werden jedoch viele Variablen nicht mehr geändert. Folglich sind diese – von einem Zeitpunkt kurz nach dem Start an – Konstanten. Wird nun erst nach diesem Zeitpunkt die Software für die System-Architektur kompiliert (dies ist bei Java Hotspot der Fall), so können diese Konstanten berücksichtigt werden. Bestimmte Verzweigungen, die nur von solchen „Halbkonstanten“ abhängig sind, sind dann für immer eindeutig und stellen somit kein Risiko für eine falsche Sprungvorhersage dar. Ein solcher Programmcode kann also schneller ablaufen als zu einem früheren Zeitpunkt kompilierter Code.

Implementierungen in Hardware 
Ausführungen in Hardware sind Java-Prozessoren, Mikroprozessoren, die Java-Bytecode als Maschinensprache verwenden. Sie konnten sich gegen die schnelle Steigerung der Leistungsfähigkeit von Standard-PC und JVM nicht durchsetzen.

Abschottung der Threads 
Die Java VM schottet die in ihr laufenden Prozesse vom Betriebssystem ab (Green Threads). Sie bildet standardmäßig Java-Threads durch Threads des Betriebssystems ab. Nur in Ausnahmefällen erfolgt das Thread-Management durch die Java VM. Somit ist es auch möglich, auf einem Betriebssystem, das kein Multithreading unterstützt, eine Java VM mit vollem Funktionsumfang anzubieten.

Die Java VM hat stets volle und standardkonforme Hoheit über die Java-Threads, d. h. der Programmierer braucht nicht die betriebssystemspezifischen Multi-Threading/Tasking/Processing-Eigenschaften zu berücksichtigen und kann sich stets auf die JRE verlassen. Nachteil ist, dass Probleme, die von einem Thread ausgehen, seitens des Betriebssystems dem gesamten Prozess zugeordnet werden. Gängige Betriebssysteme (wie zum Beispiel Linux, Windows) erlauben Kontrolle über diese „nativen“ Threads allenfalls über Software von Drittanbietern, wie beispielsweise die mit dem JDK mitgelieferte VisualVM. Standardwerkzeuge wie beispielsweise der Windows Taskmanager zeigen Systemthreads jedoch nicht an.

JVM-Sprachen 
Neben Java gibt es auch andere Sprachen, die als Programmiersprachen für JVM-Programme benutzt werden können. Unter anderem folgende Sprachen können auf einer JVM laufen:
 Clojure, ein Lisp-Dialekt,
 Ceylon,
 Concurnas, eine Multi-Paradigma-Programmiersprache für nebenläufige, verteilte und reaktive Anwendungen, mit Python-ähnlicher Syntax, Unterstützung für GPU-Computing und Off-Heap-Speicherverwaltung.
 Erjang, ein Erlang-Dialekt für die JVM,
 Free Pascal, das auch unter der JVM einen Großteil der Object-Pascal-Konstrukte unterstützt,
 Groovy, eine sehr Java-nahe, statisch wie dynamisch typisierte Programmiersprache
 JRuby, eine annähernd Ruby-kompatible Implementierung,
 Jython (früher: JPython), eine reine Java-Implementierung der Programmiersprache Python,
 Nice, ergänzt Java mit parametrische Typen, anonyme Funktionen, Multimethoden, Tupel und optionale Parameter.
 Scala, eine Sprache, die Eigenschaften von Java mit funktionaler Programmierung vereint,
 Kotlin, eine 2011 vorgestellte Sprache von JetBrains

Daneben gibt es eine Reihe von Skripting-Sprachen, die von Java aus aufrufbar sind. Dazu gehört JavaScript (mittlerweile standardisiert als ECMAScript) mit dem „Rhino“-Interpreter (ein Mozilla-Projekt) bis Version 7 bzw. mit dem „Nashorn“-Interpreter ab Version 8. Auch JavaFX enthielt in den Versionen 1.x eine Skripting-Sprache vor allem für grafische Elemente, ist aber ab Version 2.0 in pure Java implementiert.

Kompilierung in JavaScript 
Mit der kontinuierlichen Verbesserung der JavaScript-Ausführungsgeschwindigkeit, kombiniert mit der verstärkten Nutzung mobiler Geräte, deren Webbrowser keine Unterstützung für Plugins bereitstellen, gibt es Bemühungen, diese Benutzer durch Kompilierung in JavaScript anzusprechen. Es ist möglich, den Quellcode oder JVM-Bytecode nach JavaScript zu kompilieren.

Die Kompilierung des JVM-Bytecodes, der für alle JVM-Sprachen universell ist, ermöglicht es, auf dem bestehenden Compiler der Sprache aufzubauen und Bytecode zu erstellen. Die wichtigsten JVM-Bytecodes für JavaScript-Compiler sind TeaVM, der Compiler im Dragome Web SDK, Bck2Brwsr, und j2js-Compiler.

Zu den führenden Compilern von JVM-Sprachen zu JavaScript gehören der Java-zu-JavaScript-Compiler in Google Web Toolkit, Clojurescript (Clojure), GrooScript (Apache Groovy), Scala.js (Scala) und andere.

Siehe auch 
 Dalvik – eine von Google für die Android-Plattform entwickelte JVM
 HotSpot – die am weitesten verbreitete JVM von Oracle
 IBM J9
 JRockit (BEA Systems, jetzt Oracle)
 Kaffe – eine freie GPL-JVM-Implementierung
 Persistent Reusable Java Virtual Machine (PRJVM) – eine von IBM modifizierte Form der JVM
 PreonVM, virtuelle Maschine für ressourcenbeschränkte eingebettete Systeme
 SableVM – freie LGPL JVM-Implementierung

Weblinks 

 Download-Seite der JRE (inklusive der Java Virtual Machine) bei Oracle
 JVM Dokumentation bei Oracle
 Spezifikation der Java VM (englisch)
 SPECjvm, De-facto-Standard zur Messung der Leistung einer JVM

Einzelnachweise 

Java-Technologie
Virtuelle Maschine