Was ist JVM (Java Virtual Machine)?
--JVM ist eine Abkürzung für Java Virtual Machine, eine Software, die zum Ausführen von Java-Programmen erforderlich ist.
- Die Entität, die Java-Bite-Code ausführen kann.
Es kann unabhängig vom CPU- oder Betriebssystemtyp ausgeführt werden.
Mit anderen Worten, in dem Prozess, der auf dem Betriebssystem ausgeführt wird, wird der durch Kompilieren des Java-Codes erhaltene Bytecode in eine Maschinensprache konvertiert, die das entsprechende Betriebssystem (Windows, OS X, Linux usw.) verstehen (analysieren) und ausführen kann.
JVM für verschiedene Betriebssysteme
JVM-Konfiguration
Wenn Sie es allgemein betrachten, gibt es die folgenden vier.
- Class Loader
- Execution Engine
- Garbage Collector
- Runtime Data Area
JVM-Konfiguration
Class Loader
Wenn Sie in Java einen Quellcode erstellen, wird eine Java-Datei wie Test.java generiert.
Wenn der Java-Compiler die Java-Quelle kompiliert, wird eine .class-Datei (Bytecode) wie Test.class generiert.
Der Class Loader spielt die Rolle, die auf diese Weise generierte ** Class-Datei zusammenzustellen und den ** Runtime Data Area ** zu laden, den vom Betriebssystem angegebenen Speicherbereich.
Execution Engine
- Die Execution Engine konvertiert die vom Class Loader geladene Klasse (Bytecode) in eine Maschinensprache und führt sie in Einheiten von Befehlswörtern aus.
- Es gibt zwei Möglichkeiten, einen Interpreterausdruck zu verwenden, der die Befehlswörter einzeln ausführt, und einen JIT-Compiler (Just-In-Time).
- Der JIT-Compiler ist eine Methode zur Verbesserung der Leistung, indem der gesamte Bytecode zu einem geeigneten Zeitpunkt in nativen Code geändert und der nativ kompilierte Code von Execution Engine ausgeführt wird.
Garbage Collector
- Der Garbage Collector (GC) sucht und löscht nicht referenzierte Objekte unter den im Heap-Speicherbereich erstellten (geladenen) Objekten.
- Ich weiß nicht genau, wann der GC stattfinden wird. (Da wir nicht garantieren können, dass es sofort nach dem Verschwinden der Referenz veröffentlicht wird)
--Während GC ausgeführt wird, werden andere Threads als der Thread, der GC ausführt, gestoppt.
- Wenn alle Threads für einige Sekunden angehalten werden, wenn Full GC ausgeführt wird, tritt ein schwerwiegendes Problem auf, das zu einem Fehler führen kann.
Runtime Data Area
- In diesem Bereich werden Daten geladen, die beim Ausführen von Java-Anwendungen im Speicherbereich der JVM verwendet werden.
- Unterteilt in Methodenbereich, Heap-Bereich, Stapelbereich, PC-Register, nativer Methodenstapel. (Es gibt andere Vertreter.)
Struktur des Laufzeitdatenbereichs
Method area
- Der Methodenbereich ist ein Bereich, in dem Klasseninformationen für jede im Programm verwendete Klasse verwaltet werden.
- Feldinformationen und Methodennamen wie Namen von Klassenmitgliedsvariablen, Datentypen, Zugriffssteuerungsinformationen, Rückgabetypen, Parameter, Typinformationen (Schnittstelle oder Klasse), Konstanter Pool, statische Variablen, endgültige Klassenvariablen usw. Verwaltet.
Heap area
-
Der Heap-Bereich ist der Bereich, der die Instanz und die Mitgliedsfelder der Instanz verwaltet.
--Bereich zum Verwalten von Objekten und Arrays, die mit dem neuen Schlüsselwort erstellt wurden.
-
Es kann nur die im Methodenbereich geladene Klasse generiert werden, und der Garbage Collector scannt und gibt den Speicher frei, auf den nicht verwiesen wird.
Stack area
- Dies ist der Bereich für jeden Thread.
- Bereich zum Verwalten lokaler Variablen, Parameter, Rückgabewerte, beliebiger Werte, die in Operationen verwendet werden usw.
- Der Stapelbereich ist keine gemeinsam genutzte Ressource, daher ist er threadsicher.
- Der Stapelrahmen ist in drei Untereinträge unterteilt.
- Speichert die Anzahl der lokalen Variablen, die der Local Variable Array-Methode zugeordnet sind, und ihre entsprechenden Werte.
--Operand-Stapel Wenn zur Ausführung eine Zwischenoperation erforderlich ist, fungiert der Operandenstapel als Laufzeitarbeitsbereich (Arbeitsbereich) zum Ausführen der Operation.
- Hier werden alle Symbole gespeichert, die der FrameData-Methode entsprechen. Bei Ausnahmen bleiben die Fangblockinformationen in den Rahmendaten erhalten.
PC Register
--Hält den Programmzähler, einen Zeiger auf die aktuelle Anweisung, die innerhalb des Threads ausgeführt wird, in dem Bereich, der jedes Mal erstellt wird, wenn ein Thread erstellt wird. (* Unterschiedlich zu CPU-Registern)
--Wenn die aktuell ausgeführte Methode "nativ" ist, ist der Wert des Programmzählerregisters undefiniert.
Native method stack
- Ein Speicherbereich für nativen Code, der in anderen Programmiersprachen als Java geschrieben wurde.
- Normalerweise ein Stapel für die Verwendung von Code wie C / C ++. (JNI)
- JNI: JNI interagiert mit der nativen Methodenbibliothek und stellt die native Bibliothek bereit, die für die Ausführungsengine erforderlich ist.
Wenn der Thread erstellt wird
Alle Threads teilen sich den Methodenbereich und den Heap-Bereich
Der Stapelbereich, die PC-Register und der native Methodenstapel werden für jeden Thread erstellt und nicht gemeinsam genutzt.
Heap area & Garbage Collector
In diesem Artikel ist der Heap-Bereich ein wichtiges Ziel von GC. Schauen wir uns das genauer an.
(Stapelbereich und Methodenbereich unterliegen ebenfalls der GC.)
Der Heap-Bereich besteht aus 5 Bereichen (Eden, Survivor1, Survivor2, Old, Permanent).
Bis JDK7 war der permanente Bereich im Heap vorhanden. Aus JDK8 ist der permanente Bereich verschwunden und ein Teil davon wurde in den "Meta-Space-Bereich" geändert. (Die obige Abbildung basiert auf JDK7.) Der Meta-Space-Bereich ist jetzt im Native-Stack-Bereich enthalten.
(Es ist wichtig, dass die Zahlen im Überlebensbereich bedeutungslos und zweigeteilt sind.)
Der Grund, warum der Heap-Bereich in 5 unterteilt ist, besteht darin, dass die GC effizient arbeitet.
Ich möchte die Details erklären, während ich den Prozess der GC beobachte.
GC ist in Minor GC und Major GC unterteilt
* Minor GC: GC wird im neuen Bereich durchgeführt
- Wenn das Objekt zum ersten Mal erstellt wird, wird es im Bereich Eden erstellt.
- Der erste GC wird durchgeführt, wenn der Eden-Bereich voller Objekte ist.
- Die Erinnerung an den Eden-Bereich wird unverändert in den Survivor1-Bereich kopiert. Löschen Sie dann die Objekte in den anderen Bereichen außer dem Bereich "Survivor1".
- Wenn sowohl der Eden-Bereich als auch der Survivor1-Bereich voll sind, suchen Sie nach den im Eden-Bereich generierten Objekten und den im Survivor1-Bereich generierten Objekten, auf die verwiesen wird.
- Lassen Sie die nicht referenzierten Objekte unverändert und kopieren Sie nur die referenzierten Objekte in den Bereich Survivor2.
- Löschen Sie die Objekte in den anderen Bereichen außer dem Bereich Survivor2.
- Objekte, auf die im obigen Ablauf mehr als eine bestimmte Anzahl von Malen verwiesen wurde, werden vom Überlebenden2 in den alten Bereich verschoben.
- Wiederholen Sie den obigen Vorgang und wechseln Sie kontinuierlich zu Alt, bevor der Bereich für Überlebende2 voll ist.
* Major GC (Full GC): GC wird im alten Bereich durchgeführt
- Überprüfen Sie alle Objekte im alten Bereich, um festzustellen, ob auf sie verwiesen wird.
- Sammeln Sie nicht referenzierte Objekte und löschen Sie sie alle gleichzeitig.
- Es dauert länger als Minor GC und alle Threads außer GC werden gestoppt, während GC ausgeführt wird.
Was ist, wenn Major GC (Full GC) durchgeführt wird? ??
Überprüft nicht referenzierte Objekte im Bereich Alt und löscht alle zutreffenden Objekte.
In diesem Fall wird es im Heap-Speicherbereich gelöscht und freier Speicherplatz erstellt. Es wird jedoch eine Neukonfiguration durchgeführt, um diesen freien Speicher zu entfernen. (Speicherorganisation)
** Daher werden alle Threads gestoppt, um zu verhindern, dass andere Threads den Speicher verwenden, während der Speicher neu konfiguriert wird. ** **.
Referenz
- https://jeong-pro.tistory.com/m/148?category=793347
- https://gakumon.tech/java/java_thread_jvm.html