Die Java Virtual Machine (JVM) ist eine Kernkomponente der Java Runtime Environment (JRE), die es ermöglicht, Java-Programme auf jeder Plattform ohne Änderungen auszuführen. JVM fungiert als Interpreter zwischen Java-Bytecode und der zugrunde liegenden Hardware und stellt Javas berühmte WORA-Funktion (Write Once Run Anywhere) bereit.
- Java-Quelle (.java) -> kompiliert von javac -> Bytecode (.class)
- Die JVM lädt den Bytecode, überprüft die Verknüpfung und führt ihn dann aus
- Die Ausführung kann die Interpretation von Bytecode oder die Verwendung der Just-In-Time-Kompilierung (JIT) umfassen, um Hotcode aus Leistungsgründen in nativen Maschinencode umzuwandeln
- Die Garbage Collection läuft im Hintergrund, um Speicher von ungenutzten Objekten zurückzugewinnen
Architektur von JVM
Das Bild unten zeigt die Architektur und Schlüsselkomponenten von JVM.
Komponenten der JVM-Architektur
Jetzt werden wir jede Komponente der JVM im Detail besprechen.
Hallo Welt Java
1. Klassenlader-Subsystem
Es ist hauptsächlich für drei Aktivitäten verantwortlich.
1. Laden
- Liest .class-Dateien und speichert Klassenmetadaten im Methodenbereich.
- Erstellt ein Class-Objekt im Heap, das die geladene Klasse darstellt.
class GFG{ static{ System.out.println('GFG class is loaded by the JVM!'); } public void display(){ System.out.println('Method of GFG class is executed.'); } } public class Test{ public static void main(String[] args) throws Exception{ System.out.println('Main method started.'); // Loading the class explicitly using Class.forName() Class.forName('GFG'); System.out.println('Class loaded successfully.'); // Creating object to execute method GFG obj = new GFG(); obj.display(); } }
Ausgabe
Main method started. GFG class is loaded by the JVM! Class loaded successfully. Method of GFG class is executed.
Notiz: Für jede geladene .Klasse Nur Datei eins Objekt der Klasse wird erstellt.
2. Verlinkung: Verantwortlich für die Vorbereitung der geladenen Klasse für die Ausführung. Es umfasst drei Schritte:
- Überprüfung: Stellt sicher, dass der Bytecode den JVM-Regeln entspricht und sicher ausgeführt werden kann.
- Vorbereitung: Reserviert Speicher für statische Variablen und weist Standardwerte zu.
- Auflösung: Konvertiert symbolische Referenzen in direkte Referenzen im Speicher.
3. Initialisierung
- Weist statischen Variablen tatsächliche Werte zu.
- Führt in der Klasse definierte statische Blöcke aus.
Klassenladertypen
- Bootstrap-Klassenlader: Lädt Java-Kernklassen (JAVA_HOME/lib).
- Erweiterungsklassenlader: Lädt Klassen aus dem Erweiterungsverzeichnis (JAVA_HOME/jre/lib/ext).
- System-/Anwendungsklassenlader: Lädt Klassen aus dem Anwendungsklassenpfad.
// Java code to demonstrate Class Loader subsystem public class Geeks { public static void main(String[] args) { // String class is loaded by bootstrap loader and // bootstrap loader is not Java object hence null System.out.println(String.class.getClassLoader()); // Test class is loaded by Application loader System.out.println(Geeks.class.getClassLoader()); } }
Ausgabe
null jdk.internal.loader.ClassLoaders$AppClassLoader@8bcc55f
2. JVM-Speicherbereiche
- Methodenbereich: Speichert Informationen auf Klassenebene wie Klassennamen, übergeordnete Klassenmethoden, Variablen und statische Daten. Wird in der gesamten JVM geteilt.
- Heap-Bereich: Speichert alle Objekte. Wird in der gesamten JVM geteilt.
- Stapelbereich: Jeder Thread verfügt über einen eigenen Laufzeitstapel. speichert Methodenaufrufe lokale Variablen in Stapelrahmen. Wird zerstört, wenn der Thread endet.
- PC-Register: Halten Sie die Adresse der aktuell ausgeführten Anweisung für jeden Thread bereit.
- Native Methodenstapel: Jeder Thread verfügt über einen separaten Stapel für die Ausführung nativer Methoden.
3. Ausführungs-Engine
Die Ausführungs-Engine führt die .class (Bytecode) aus. Es liest den Bytecode Zeile für Zeile, verwendet Daten und Informationen in verschiedenen Speicherbereichen und führt Anweisungen aus. Es kann in drei Teile eingeteilt werden:
TCP-IP-Modell
- Interpreter: Es interpretiert den Bytecode Zeile für Zeile und führt ihn dann aus. Der Nachteil hierbei ist, dass bei mehrmaligem Aufruf einer Methode jedes Mal eine Interpretation erforderlich ist.
- Just-In-Time-Compiler (JIT): Es wird verwendet, um die Effizienz eines Dolmetschers zu steigern. Es kompiliert den gesamten Bytecode und wandelt ihn in nativen Code um. Immer wenn der Interpreter wiederholte Methodenaufrufe sieht, stellt JIT direkten nativen Code für diesen Teil bereit, sodass keine Neuinterpretation erforderlich ist und die Effizienz verbessert wird.
- Müllsammler: Es zerstört nicht referenzierte Objekte. Weitere Informationen zum Garbage Collector finden Sie unter Müllsammler .
4. Java Native Interface (JNI)
Es handelt sich um eine Schnittstelle, die mit den nativen Methodenbibliotheken interagiert und die für die Ausführung erforderlichen nativen Bibliotheken (C C++) bereitstellt. Es ermöglicht der JVM, C/C++-Bibliotheken aufzurufen und von C/C++-Bibliotheken aufgerufen zu werden, die möglicherweise hardwarespezifisch sind.
5. Native Methodenbibliotheken
Hierbei handelt es sich um Sammlungen nativer Bibliotheken, die zum Ausführen nativer Methoden erforderlich sind. Dazu gehören Bibliotheken, die in Sprachen wie C und C++ geschrieben sind.