In diesem Artikel wird hauptsächlich über den Java-Speicherzuweisungs- und Recyclingmechanismus gesprochen, der hauptsächlich JavaLaufzeitdatenbereich, Objekterstellung, Garbage-Collection-Algorithmus mit umfasst Recyclingstrategie.
Siehe den PHP-Chinesisch-Website-Kurs „JAVA Elementary Introduction Video Tutorial“. Der Autor hat gerade die Kultur basierend auf dem Inhalt des Tutorials zusammengefasst und illustriert. Dieser Teil des Inhalts ist nahezu vollständig verständlich und wird möglichst in Form von Bildern, Texten oder Tabellen dargestellt.
Die folgende Abbildung ist ein Speicherdiagramm der Java Virtual Machine, wenn sie ausgeführt wird:
Auf dem Bild können wir sehen, dass der Java-Speicher in 6 Teile unterteilt ist:
Programmzähler: Jeder Thread verfügt über einen unabhängigen Programmzähler , und der Zähler kann als Zeilennummernanzeige des vom aktuellen Thread ausgeführten Bytecodes betrachtet werden. Wenn der Bytecode-Interpreter funktioniert, ändert er den Wert dieses Zählers, um die nächste Bytecode-Anweisung, Verzweigung, Schleife , Sprung, Ausnahmebehandlung auszuwählen, die ausgeführt werden muss, Grundfunktionen wie Die Thread-Wiederherstellung basiert auf diesem Zähler.
Java Virtual Machine Stack: Der Virtual Machine Stack ist privat für den Thread und der Lebenszyklus ist derselbe wie der Thread. Der Stapel der virtuellen Maschine beschreibt das Speicher--Modell für die Java-Methodenausführung. Wenn jede Methode ausgeführt wird, wird ein Stapelrahmen erstellt, um die lokale -Variablen--Tabelle, den Operandenstapel, die dynamische Verknüpfung usw. zu speichern Methode. Export und andere Informationen. Der Prozess vom Aufruf bis zum Abschluss jeder Methode entspricht dem Prozess vom Schieben eines Stapelrahmens in den Stapel der virtuellen Maschine bis zum Herausspringen.
Lokaler Methodenstapel: Er spielt eine ähnliche Rolle wie der Stapel der virtuellen Maschine. Der Unterschied besteht darin, dass der Stapel der virtuellen Maschine die Ausführung von Java-Methoden übernimmt und der Stapel lokaler Methoden native Methoden .
Eine Region, die von allen Threads gemeinsam genutzt wird. Beim Start der virtuellen Maschine erstellt, werden fast alle Objektinstanzen auf dem Heap zugewiesen. Der Java-Heap kann auch unterteilt werden in: die neue Generation und die alte Generation. Im Detail gibt es den Eden-Raum, den From-Survivor-Raum und den To-Survivor-Raum. Unabhängig von der Aufteilung werden jedoch alle Objektinstanzen gespeichert. Der Zweck der weiteren Aufteilung besteht darin, Speicher besser zurückzugewinnen oder Speicher schneller zuzuweisen.
Der Methodenbereich ist ein von jedem Thread gemeinsam genutzter Speicherbereich. Er wird hauptsächlich zum Speichern von Klasseninformationen verwendet, die von der virtuellen Maschine geladen wurden, Konstanten, Statische Variablen, spontan kompilierter Code und andere Daten. Dieser Bereich erfordert keinen kontinuierlichen Speicher wie der Java-Heap und kann fest oder erweiterbar sein. Sie können sich auch dafür entscheiden, keine Garbage Collection zu implementieren. Das Ziel des Speicherrecyclings in diesem Bereich besteht hauptsächlich darin, konstante Pools zu recyceln und Arten von Speicherbereinigungen zu entladen. Verhalten kommt in diesem Bereich selten vor.
Schnittstelle enthält die Klasse-Datei auch einen Konstantenpool, der zum Speichern verschiedener generierter Daten verwendet wird während der Kompilierung. Die Literalzeichen und Symbole beziehen sich auf . Dieser Teil des Inhalts wird nach dem Laden der Klasse im Laufzeitkonstantenpool gespeichert.
Direkter Speicher wird auch Off-Heap-Speicher genannt. Er ist nicht Teil des Datenbereichs, wenn die virtuelle Maschine ausgeführt wird. Die NIO-Klasse wurde nach JDK1.4 eingeführt, einer E/A-Methode, die auf Channel und Buffer basiert. Sie kann die NativeFunction-Bibliothek verwenden, um Speicher direkt außerhalb des Heaps zuzuweisen und ihn dann über The zu speichern Das DirectByteBuffer-Objekt im Java-Heap verwendet diesen Speicher als Referenz. Dies kann die Leistung erheblich verbessern und das Hin- und Herkopieren von Daten zwischen dem Java-Heap und dem nativen Heap vermeiden.
数据区域 | 概括 | 线程共享 |
---|---|---|
程序计数器 | 当前线程所执行的字节码的行号指示器 | 否 |
虚拟机栈 | 为Java方法执行创建栈帧存储局部变量、操作数栈、动态链接、方法出口等信息 | 否 |
本地方法栈 | 与虚拟机栈类似,为Native方法服务 | 否 |
堆 | 存放对象实例 | 是 |
方法区 | 存储虚拟机已加载的类信息、常量、静态变量、即时编译后的代码等数据 | 是 |
运行时常量池 | 方法区的一部分,存放编译期生成的字面量和符号引用 | 是 |
直接内存 | 被分配在堆外的内存,性能高,不受Java堆的大小限制 | 是 |
Das obige Bild ist das vollständige Flussdiagramm der Objekterstellung, das im Folgenden ausführlich erläutert wird.
neue-Anweisung empfängt, prüft sie, ob die Parameter dieser Anweisung eine Symbolreferenz einer Klasse im Konstantenpool finden können, und Überprüft, ob die durch diese Symbolreferenz dargestellte Klasse geladen, aufgelöst und initialisiert wurde. Wenn nicht, muss zuerst der Klassenladevorgang durchgeführt werden.
Zeigerkollision“ bezeichnet. Wenn der Speicher im Java-Heap nicht regelmäßig ist und freier Speicher und verwendeter Speicher verschachtelt sind, muss die virtuelle Maschine eine Liste führen, um aufzuzeichnen, welche Speicherblöcke verfügbar sind, und beim Zuweisen von Objektinstanzen und Objektinstanzen genügend Speicherplatz aus der Liste ermitteln, um ihn zuzuweisen Aktualisieren Sie den Datensatz in der -Liste. Diese Zuordnungsmethode wird „freie Liste“ genannt. Welche Zuordnungsmethode verwendet wird, hängt normalerweise davon ab, ob der Garbage Collector der virtuellen Maschine über eine Komprimierungsfunktion verfügt.
sicher ist, wenn Sie Speicherplatz für Objektinstanzen zuweisen. Um die Thread-Sicherheit zu gewährleisten, gibt es zwei Möglichkeiten. Eine besteht darin, die Aktion der Speicherzuweisung zu synchronisieren . Tatsächlich verwendet die virtuelle Maschine CAS mit fehlgeschlagenem Wiederholungsversuch, um die Atomizität des Aktualisierungsvorgangs sicherzustellen. Die andere besteht darin, die Speicherzuweisungsaktion entsprechend den Threads in verschiedene Bereiche aufzuteilen. Jeder Thread weist im Java-Heap vorab einen kleinen Speicherbereich zu, der als Lokaler Thread-Zuweisungspuffer(Thread Local Allocation Buffer, TLAB) bezeichnet wird. . Welcher Thread Speicher zuweisen möchte, weist ihn dem TLAB dieses Threads zu. Eine Synchronisierungssperre ist nur erforderlich, wenn der TLAB aufgebraucht ist und ein neuer TLAB zugewiesen wird.
zugewiesenen Speicherplatz auf den Nullwert (mit Ausnahme des Objektheaders) und stellt so sicher, dass das Instanzfeld vorhanden ist des Objekts ist in Java. Es kann direkt im Code verwendet werden, ohne einen Anfangswert zuzuweisen.
Informationen des Objekts in den Objektheader des Objekts ein.
Das Speicherlayout eines Objekts ist in drei Teile unterteilt:
Objektkopf Es umfasst hauptsächlich zwei Teile von Informationen:
Laufzeitdaten verwendet, wie z. B. Hash-Code, GC Generationsalter, Sperre Status Flag, vom Thread gehaltene Sperre, voreingenommene Thread-ID, voreingenommener Zeitstempel usw.
Typzeiger, der der Zeiger des Objekts auf seine Klassenmetadaten ist. Die virtuelle Maschine verwendet diesen Zeiger, um zu bestimmen, welche Klasse das Objekt hat ist ein Beispiel für. Wenn es sich bei dem Objekt um ein JavaArray handelt, muss im Objektheader ein Datenelement vorhanden sein, das die Länge des Arrays aufzeichnet.
Der Instanzdatenteil ist die effektive Information, die tatsächlich vom Objekt gespeichert wird, und es ist auch der Inhalt verschiedener Arten von Feldern, die im Programm definiert sind Code. Alles, was von der übergeordneten Klasse geerbt und in der Unterklasse definiert wird, muss aufgezeichnet werden.
Polsterung ausrichten fungiert nur als Platzhalter. Das automatische Speicherverwaltungssystem von HotSpot VM erfordert, dass die Objektstartadresse ein ganzzahliges Vielfaches von 8 Bytes ist, daher muss die Objektgröße ein ganzzahliges Vielfaches von 8 Bytes sein. Wenn der Datenteil der Objektinstanz nicht ausgerichtet ist, muss er durch Ausrichtungsauffüllung vervollständigt werden.
Die Java Virtual Machine ermittelt durch Erreichbarkeitsanalyse . Die Grundidee dieses Algorithmus besteht darin, eine Reihe von Objekten namens „GC Roots“ als Ausgangspunkt zu verwenden und von diesen Knoten aus nach unten zu suchen Der von der Suche zurückgelegte Pfad wird als Referenzkette bezeichnet. Wenn ein Objekt GC Roots erreicht, ist das Objekt nicht verfügbar, wenn es mit keiner Referenzkette verbunden ist.
Wie in der Abbildung gezeigt, sind Objekt5, Objekt6 und Objekt7 miteinander verbunden, aber die GC-Wurzeln sind nicht erreichbar, sodass sie als recycelbare Objekte beurteilt werden.
Eine weitere erwähnenswerte Sache ist der Referenzzählalgorithmus, bei dem dem Objekt immer dann ein Referenzzähler zugewiesen wird, wenn die Referenz fehlschlägt. der Zählerwert wird um 1 dekrementiert; ein Objekt, dessen Zähler zu jedem Zeitpunkt 0 ist, kann nicht mehr verwendet werden. Referenzzähler sind effizient und einfach zu implementieren. Es ist jedoch schwierig, das Problem der zirkulären Referenzen zwischen Objekten zu lösen. Fast alle gängigen virtuellen Java-Maschinen verwenden keine Referenzzählung mehr zur Speicherverwaltung .
Auch wenn das Objekt im Erreichbarkeitsanalysealgorithmus nicht erreichbar ist, ist dies möglicherweise nicht sofort der Fall recycelt. Wenn ein Gegenstand recycelt wird, muss er den Markierungsprozess mindestens zweimal durchlaufen.
Wenn das Objekt nach der Erreichbarkeitsanalyse keine mit GC Roots verbundene Referenzkette hat, wird es zum ersten Mal markiert und einmal gefiltert. Die Filterbedingung besteht darin, ob dieses Objekt die finalize()-Methode ausführen muss. Wenn das Objekt die finalize()-Methode nicht abdeckt oder die finalize()-Methode von der virtuellen Maschine aufgerufen wurde, behandelt die virtuelle Maschine diese beiden Situationen als „keine Ausführung erforderlich“.
Wenn festgestellt wird, dass dieses Objekt zum Ausführen der finalize()-Methode erforderlich ist, wird dieses Objekt in die F-WarteschlangeWarteschlange gestellt, die später automatisch von der virtuellen Maschine erstellt wird PrioritätDer Finalizer-Thread führt die finalize()-Methode aus. Der GC führt eine zweite kleine Markierung für das Objekt in der F-Warteschlange durch. Wenn das Objekt erneut mit einem Objekt in der Referenzkette verknüpft wird, wird es während der zweiten Markierung aus der Sammlung „bald recycelt“ entfernt . Andernfalls wird das Objekt wirklich recycelt.
Das Recycling des Methodenbereichs umfasst hauptsächlich zwei Teile . : Veraltete Konstanten und Nutzlose Klassen.
Das Recycling verworfener Konstanten ähnelt dem Recycling von Objekten im Java-Heap.
Die Bedingungen für die Beurteilung einer nutzlosen Klasse müssen drei Bedingungen erfüllen:
Alle Instanzen dieser Klasse wurden recycelt.
Der ClassLoader, der diese Klasse geladen hat, wurde recycelt.
Das java.lang.Class-Objekt, das dieser Klasse entspricht, wird nirgendwo referenziert, und auf die Klasse kann nicht durch Reflektion zugegriffen werden.
Mark-Sweep-Algorithmus (Mark-Sweep) :
Der Algorithmus ist in zwei Phasen unterteilt: „Markieren“ und „Löschen“: Markieren Sie zunächst die Objekte, die recycelt werden müssen, und nachdem die Markierung abgeschlossen ist, werden die markierten Objekte einheitlich recycelt. Es weist zwei Hauptmängel auf: Erstens Effizienzprobleme, sowohl der Markierungs- als auch der Clearingprozess sind nicht sehr effizient. Das zweite ist das Speicherplatzproblem. Nach dem Löschen der Markierung wird eine große Anzahl diskontinuierlicher Speicherfragmente generiert, wenn ein größeres Objekt zugewiesen wird Die Garbage-Collection-Aktion muss im Voraus ausgelöst werden.
Kopieralgorithmus :
Kopieralgorithmus Teilen Sie den verfügbaren Speicher entsprechend der Kapazität in zwei gleich große Blöcke auf und verwenden Sie jeweils nur einen Block. Wenn ein Speicherblock erschöpft ist, kopieren Sie die verbleibenden -Objekte in einen anderen Block und bereinigen Sie dann sofort den verwendeten Speicherplatz. Dadurch kann jedes Mal der gesamte halbe Bereich recycelt werden, und bei der Speicherzuweisung muss nicht auf die Speicherfragmentierung geachtet werden. Bewegen Sie einfach den oberen Zeiger des Heaps und weisen Sie den Speicher der Reihe nach zu. , Effizient laufen. Es ist nur so, dass dieser Algorithmus den Speicher auf die Hälfte der ursprünglichen Größe reduziert, was teurer ist.
Mark-Collation-Algorithmus (Mark-Compact) :
Der Markierungsprozess ist derselbe wie beim „Mark-Clear“-Algorithmus, aber anstatt wiederverwendbare Objekte direkt zu bereinigen, werden alle überlebenden Objekte an ein Ende verschoben und dann wird der Speicher außerhalb der Endgrenze direkt gelöscht
4.Generational Collection-Algorithmus
Kommerziell Die Garbage Collection virtueller Maschinen verwendet einen Generationssammlungsalgorithmus, der den Speicher entsprechend dem Überlebenszyklus des Objekts in mehrere Blöcke aufteilt. Der Java-Heap ist in Neue Generation und Alte Generation unterteilt, sodass entsprechend den Merkmalen der Ära geeignete Erfassungsalgorithmen verwendet werden können. Bei jeder Speicherbereinigung in der neuen Generation sterben viele Objekte. Verwenden Sie daher den Replikationsalgorithmus. Die Überlebensrate von Objekten der alten Generation ist hoch und es gibt keinen zusätzlichen Platz für die Zuweisungsgarantie. Sie eignen sich für das Recycling mit dem „Mark-Clean“- oder „Mark-Organize“-Algorithmus.
Objekte werden in der Eden-Partition priorisiert:
In den meisten Fällen werden Objekte im Eden-Bereich der neuen Generation zugewiesen. Wenn der Eden-Bereich nicht über genügend Speicherplatz verfügt, initiiert die virtuelle Maschine einen Minor GC. Nach der GC wird versucht, das Objekt in den Survivor-Bereich zu platzieren. Wenn der Survivor-Bereich das Objekt nicht darin ablegen kann, kann es nur über den Mechanismus zur Gewährleistung der Speicherplatzzuweisung im Voraus an die alte Generation übertragen werden.
Große Objekte gelangen direkt in die alte Generation:
Große Objekte beziehen sich auf Java-Objekte, die viel kontinuierlichen Speicherplatz benötigen. Die virtuelle Maschine stellt den Parameter -XX:PretenureSizeThreshold bereit. Wenn das Objekt größer als dieser Einstellungswert ist, wird das Objekt direkt in der alten Generation zugewiesen. Dadurch kann eine große Menge an Speicherkopien im Eden-Bereich und den beiden Survivor-Bereichen in der neuen Generation vermieden werden.
Langfristig überlebende Objekte treten in die alte Generation ein:
Die virtuelle Maschine definiert für jedes Objekt einen Objektalterszähler. Wenn das Objekt in Eden geboren wurde und nach einem Minor GC noch überlebt und vom Survivor aufgenommen werden kann, wird es in den Survivor-Bereich verschoben und das Objektalter wird auf 1 gesetzt. Nach jedem Minor GC überlebt das Objekt noch im Survivor-Bereich und im Alter Fügen Sie einfach eins hinzu. Wenn das Alter den durch den Parameter -XX:MaxTenuringThreshold festgelegten Wert erreicht, wird es in die alte Generation verschoben.
Dynamische Altersbeurteilung:
Die virtuelle Maschine erfordert nicht immer, dass das Alter des Objekts den durch -XX:MaxTenuringThreshold festgelegten Wert erreichen muss, bevor das Objekt in die verschoben wird alte Generation. Wenn die Summe der Größen aller gleichaltrigen Objekte im Survivor größer als die Hälfte des Survivor-Raums ist, können Objekte, deren Alter größer oder gleich diesem Alter ist, direkt in die alte Generation eintreten.
Speicherplatzzuweisungsgarantie:
Vor Minor GC prüft die virtuelle Maschine, ob der maximal verfügbare kontinuierliche Speicherplatz in der alten Generation größer ist als der Gesamtspeicherplatz aller Objekte in der neuen Generation . Wenn die Bedingung wahr ist, wird der Minor GC eingerichtet. Wenn nicht, prüft die virtuelle Maschine, ob der HandlePromotionFailure-Einstellungswert einen Garantiefehler zulässt. Wenn dies zulässig ist, wird weiterhin geprüft, ob der maximal verfügbare kontinuierliche Speicherplatz in der alten Generation größer ist als die durchschnittliche Größe der in die alte Generation verschobenen Objekte. Wenn er größer ist, wird ein Minor GC versucht. Wenn der Wert kleiner ist oder der Einstellungswert von HandlePromotionFailure kein Risiko zulässt, wird eine vollständige GC durchgeführt.
GC der neuen Generation (Minor GC): Garbage-Collection-Aktion, die in der neuen Generation auftritt. Da die meisten Java-Objekte schnell sterben, ist Minor GC sehr häufig und die Recyclinggeschwindigkeit ist hoch relativ langsam.
GC der alten Generation (Major GC/Full GC): Garbage-Collection-Aktionen, die in der alten Generation stattfinden. Major GC wird oft von mindestens einem Minor GC begleitet. Die Geschwindigkeit von Major GC ist im Allgemeinen mehr als zehnmal langsamer als die von Minor GC.
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung des Java-Speicherzuweisungs- und Recyclingmechanismus (Bild). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!