In Java ist Speicherverwaltung der Prozess der Zuweisung und Freigabe von Objekten, der als Speicherverwaltung bezeichnet wird. Java führt die Speicherverwaltung automatisch durch. Java verwendet ein automatisches Speicherverwaltungssystem namens a Müllsammler . Daher müssen wir in unserer Anwendung keine Speicherverwaltungslogik implementieren. Die Java-Speicherverwaltung gliedert sich in zwei Hauptteile:
JVM-Speicherstruktur
JVM erstellt verschiedene Laufzeitdatenbereiche in einem Heap. Diese Bereiche werden während der Programmausführung verwendet. Die Speicherbereiche werden beim Beenden der JVM zerstört, wohingegen die Datenbereiche beim Beenden des Threads zerstört werden.
Methodenbereich
Der Methodenbereich ist ein Teil des Heap-Speichers, der von allen Threads gemeinsam genutzt wird. Es wird erstellt, wenn die JVM gestartet wird. Es wird zum Speichern der Klassenstruktur, des Superklassennamens, des Schnittstellennamens und der Konstruktoren verwendet. Die JVM speichert die folgenden Arten von Informationen im Methodenbereich:
- Ein vollständig qualifizierter Name eines Typs (z. B. String)
- Die Modifikatoren des Typs
- Der direkte Superklassenname des Typs
- Eine strukturierte Liste der vollständig qualifizierten Namen von Superschnittstellen.
Heap-Bereich
Heap speichert die tatsächlichen Objekte. Es wird erstellt, wenn die JVM gestartet wird. Der Benutzer kann den Heap bei Bedarf steuern. Die Größe kann fest oder dynamisch sein. Wenn Sie ein neues Schlüsselwort verwenden, erstellt die JVM eine Instanz für das Objekt in einem Heap. Während die Referenz dieses Objekts im Stapel gespeichert wird. Für jeden laufenden JVM-Prozess gibt es nur einen Heap. Wenn der Heap voll ist, wird der Müll gesammelt. Zum Beispiel:
StringBuilder sb= new StringBuilder();
Die obige Anweisung erstellt ein Objekt der StringBuilder-Klasse. Das Objekt wird dem Heap zugewiesen, und die Referenz wird von sb dem Stapel zugewiesen. Der Heap ist in folgende Teile unterteilt:
- Junge Generation
- Überlebensraum
- Alte Generation
- Permanente Generation
- Code-Cache
Referenztyp
Es gibt vier Arten von Referenzen: Stark , Schwach , Weich , Und Phantom-Referenz . Der Unterschied zwischen den Referenztypen besteht darin, dass die Objekte auf dem Heap, auf die sie verweisen, gemäß den verschiedenen Kriterien für die Garbage Collection geeignet sind.
Starke Referenz: Es ist sehr einfach, da wir es in unserer täglichen Programmierung verwenden. Jedes Objekt, an das eine starke Referenz angehängt ist, ist nicht für die Garbage Collection geeignet. Mit der folgenden Anweisung können wir eine starke Referenz erstellen:
StringBuilder sb= new StringBuilder();
Schwache Referenz: Es überlebt den nächsten Garbage-Collection-Vorgang nicht mehr. Wenn wir nicht sicher sind, wann die Daten erneut angefordert werden. In diesem Zustand können wir einen schwachen Verweis darauf erstellen. Falls der Garbage Collector eine Verarbeitung durchführt, zerstört er das Objekt. Wenn wir erneut versuchen, dieses Objekt abzurufen, erhalten wir einen Nullwert. Es ist definiert in java.lang.ref.WeakReference Klasse. Mit der folgenden Anweisung können wir eine schwache Referenz erstellen:
WeakReference reference = new WeakReference(new StringBuilder());
Weiche Referenz: Es wird erfasst, wenn der Speicher der Anwendung knapp wird. Der Garbage Collector sammelt nicht die sanft erreichbaren Objekte. Alle Soft-referenzierten Objekte werden erfasst, bevor ein OutOfMemoryError ausgelöst wird. Mit der folgenden Anweisung können wir eine Soft-Referenz erstellen:
SoftReference reference = new SoftReference(new StringBuilder());
Phantom-Referenz: Es ist erhältlich in java.lang.ref Paket. Es ist definiert in java.lang.ref.PhantomReference Klasse. Das Objekt, auf das nur eine Phantomreferenz verweist, kann immer dann gesammelt werden, wenn der Garbage Collector eine Sammlung durchführen möchte. Mit der folgenden Anweisung können wir eine Phantomreferenz erstellen:
PhantomReference reference = new PhantomReference(new StringBuilder());
Stapelbereich
Der Stapelbereich wird generiert, wenn ein Thread erstellt wird. Die Größe kann entweder fest oder dynamisch sein. Der Stapelspeicher wird pro Thread zugewiesen. Es dient der Speicherung von Daten und Teilergebnissen. Es enthält Verweise auf Heap-Objekte. Außerdem enthält es den Wert selbst und nicht einen Verweis auf ein Objekt aus dem Heap. Die im Stapel gespeicherten Variablen haben eine bestimmte Sichtbarkeit, die als Gültigkeitsbereich bezeichnet wird.
Stapelrahmen: Der Stapelrahmen ist eine Datenstruktur, die die Daten des Threads enthält. Thread-Daten stellen den Status des Threads in der aktuellen Methode dar.
- Es dient der Speicherung von Teilergebnissen und Daten. Es führt auch dynamische Verknüpfungen durch, gibt Werte durch Methoden zurück und löst Ausnahmen aus.
- Wenn eine Methode aufgerufen wird, wird ein neuer Frame erstellt. Der Frame wird zerstört, wenn der Aufruf der Methode abgeschlossen ist.
- Jeder Frame enthält ein eigenes Local Variable Array (LVA), einen Operanden Stack (OS) und Frame Data (FD).
- Die zur Kompilierungszeit ermittelten Größen von LVA, OS und FD.
- Zu jedem Zeitpunkt in einem bestimmten Steuerungsthread ist nur ein Frame (der Frame für die Ausführung der Methode) aktiv. Dieser Frame wird als aktueller Frame bezeichnet, und seine Methode wird als aktuelle Methode bezeichnet. Die Klasse der Methode wird als aktuelle Klasse bezeichnet.
- Der Frame stoppt die aktuelle Methode, wenn ihre Methode eine andere Methode aufruft oder wenn die Methode abgeschlossen wird.
- Der von einem Thread erstellte Frame ist für diesen Thread lokal und kann von keinem anderen Thread referenziert werden.
Nativer Methodenstapel
Es wird auch als C-Stack bezeichnet. Es handelt sich um einen Stack für nativen Code, der in einer anderen Sprache als Java geschrieben ist. Java Native Interface (JNI) ruft den nativen Stack auf. Die Leistung des nativen Stacks hängt vom Betriebssystem ab.
Websites wie bedpage
PC-Register
Jedem Thread ist ein Programmzählerregister (PC) zugeordnet. Das PC-Register speichert die Rücksprungadresse oder einen nativen Zeiger. Es enthält auch die Adresse der aktuell ausgeführten JVM-Anweisungen.
Arbeitsweise des Garbage Collectors
Garbage Collector-Übersicht
Wenn ein Programm in Java ausgeführt wird, nutzt es den Speicher auf unterschiedliche Weise. Der Heap ist ein Teil des Speichers, in dem sich Objekte befinden. Es ist der einzige Teil des Speichers, der am Garbage-Collection-Prozess beteiligt ist. Es wird auch als Müllsammelhaufen bezeichnet. Die gesamte Speicherbereinigung stellt sicher, dass der Heap über so viel freien Speicherplatz wie möglich verfügt. Die Funktion des Garbage Collectors besteht darin, die nicht erreichbaren Objekte zu finden und zu löschen.
Objektzuordnung
Wenn ein Objekt zugewiesen wird, überprüft die JRockit-JVM die Größe des Objekts. Dabei wird zwischen kleinen und großen Objekten unterschieden. Die kleine und große Größe hängt von der JVM-Version, der Heap-Größe, der Garbage-Collection-Strategie und der verwendeten Plattform ab. Die Größe eines Objekts liegt normalerweise zwischen 2 und 128 KB.
Die kleinen Objekte werden im Thread Local Area (TLA) gespeichert, einem freien Teil des Heaps. TLA synchronisiert sich nicht mit anderen Threads. Wenn TLA voll ist, wird neues TLA angefordert.
Andererseits werden große Objekte, die nicht in die TLA passen, direkt dem Heap zugewiesen. Wenn ein Thread den jungen Speicherplatz verwendet, wird er direkt im alten Speicherplatz gespeichert. Das große Objekt erfordert mehr Synchronisierung zwischen den Threads.
Was macht Java Garbage Collector?
JVM steuert den Garbage Collector. Die JVM entscheidet, wann die Garbage Collection durchgeführt wird. Wir können die JVM auch auffordern, den Garbage Collector auszuführen. Es gibt jedoch unter keinen Umständen eine Garantie dafür, dass die JVM die Anforderungen erfüllt. JVM führt den Garbage Collector aus, wenn es feststellt, dass der Speicher knapp wird. Wenn ein Java-Programm den Garbage Collector anfordert, erteilt die JVM die Anforderung normalerweise in kurzer Zeit. Es stellt nicht sicher, dass die Anfragen angenommen werden.
Der Punkt, den es zu verstehen gilt, ist, dass „ Wann kommt ein Objekt für die Garbage Collection infrage? '
Jedes Java-Programm hat mehr als einen Thread. Jeder Thread hat seinen Ausführungsstapel. Es gibt einen Thread zum Ausführen in einem Java-Programm, bei dem es sich um eine main()-Methode handelt. Jetzt können wir sagen, dass ein Objekt für die Garbage Collection geeignet ist, wenn kein Live-Thread darauf zugreifen kann. Der Garbage Collector betrachtet dieses Objekt als löschbar. Wenn ein Programm über eine Referenzvariable verfügt, die auf ein Objekt verweist, ist diese Referenzvariable für den Live-Thread verfügbar und dieses Objekt wird aufgerufen erreichbar .
Hier stellt sich die Frage: „ Kann einer Java-Anwendung der Speicher ausgehen? '
Die Antwort ist ja. Das Garbage-Collection-System versucht, Objekte aus dem Speicher zu entfernen, wenn sie nicht verwendet werden. Wenn Sie jedoch viele Live-Objekte verwalten, garantiert die Garbage Collection nicht, dass genügend Speicher vorhanden ist. Nur der verfügbare Speicher wird effektiv verwaltet.
Arten der Garbage Collection
Es gibt fünf Arten der Speicherbereinigung:
Mark-and-Sweep-Algorithmus
JRockit JVM verwendet den Mark- und Sweep-Algorithmus zur Durchführung der Garbage Collection. Es enthält zwei Phasen, die Mark-Phase und die Sweep-Phase.
Markierungsphase: Objekte, auf die über Threads, native Handles und andere GC-Stammquellen zugegriffen werden kann, werden als live markiert. Jeder Objektbaum hat mehr als ein Wurzelobjekt. GC-Root ist immer erreichbar. Also jedes Objekt, dessen Wurzel einen Garbage-Collection-Root hat. Es identifiziert und markiert alle in Gebrauch befindlichen Objekte, der Rest kann als Müll betrachtet werden.
Sweep-Phase: In dieser Phase wird der Heap durchquert, um die Lücke zwischen den lebenden Objekten zu finden. Diese Lücken werden in der Freiliste erfasst und stehen für eine neue Objektvergabe zur Verfügung.
Es gibt zwei verbesserte Versionen von Mark und Sweep:
Gleichzeitiges Markieren und Sweepen
Dadurch können die Threads während eines großen Teils der Garbage Collection weiter ausgeführt werden. Es gibt folgende Arten der Markierung:
Paralleles Markieren und Sweepen
Es nutzt die gesamte verfügbare CPU im System, um die Garbage Collection so schnell wie möglich durchzuführen. Es wird auch als paralleler Garbage Collector bezeichnet. Threads werden nicht ausgeführt, wenn die parallele Garbage Collection ausgeführt wird.
Vorteile von Mark and Sweep
Post-Order-Traversal
- Es ist ein wiederkehrender Prozess.
- Es ist eine Endlosschleife.
- Während der Ausführung eines Algorithmus ist kein zusätzlicher Overhead zulässig.
Nachteile von Mark und Sweep
- Es stoppt die normale Programmausführung, während der Garbage-Collection-Algorithmus ausgeführt wird.
- Es wird mehrmals in einem Programm ausgeführt.