Heim > Java > javaLernprogramm > Hauptteil

Was ist der Java-Garbage-Collection-Mechanismus?

零下一度
Freigeben: 2017-06-25 11:04:18
Original
1309 Leute haben es durchsucht

1. Probleme

Der Autor ist in letzter Zeit auf viele Probleme mit dem Garbage-Collection-Mechanismus in Java gestoßen, daher habe ich speziell einen Blog geschrieben, um Ihnen mitzuteilen, was Garbage-Collection in Java ist. Die sogenannte Garbage Collection bedeutet, dass selbst dann ein Problem auftritt, wenn der JVM denkt, dass Ihr Objekt nicht existieren muss und Sie bereinigt.

  1. Wie kann festgestellt werden, ob ein Gegenstand recycelt werden muss?

  2. Wie recycelt ein typischer Garbage-Collection-Algorithmus Objekte?

  3. Was sind die typischen Müllsammler?

Lassen Sie mich nun die Probleme einzeln betrachten

2. Wie stellt man fest, ob ein Objekt recycelt werden muss

Hier verstehen wir zunächst Eines der Probleme: Was passiert, wenn festgestellt wird, dass ein Objekt „Müll“ ist? Da die Aufgabe des Garbage Collectors darin besteht, den von Garbage-Objekten belegten Platz für neue Objekte freizugeben, stellt sich die Frage: Wie stellt der Garbage Collector fest, dass es sich bei einem Objekt um „Müll“ handelt? – Das heißt, wie man feststellt, ob ein Objekt recycelt werden kann. Einige Objekte sind nicht mehr im JVM-Speicher und müssen bereinigt werden. Die Objekte, die in der nächsten Runde recycelt werden müssen, werden bereinigt.

In Java werden Objekte durch Referenzen verknüpft. Das heißt, wenn Sie ein Objekt bedienen möchten, müssen Sie dies über Referenzen tun. Eine einfache Möglichkeit besteht also offensichtlich darin, mithilfe der Referenzzählung zu bestimmen, ob ein Objekt recycelt werden kann. Ohne Einschränkung der Allgemeingültigkeit: Wenn einem Objekt keine Referenzen zugeordnet sind, bedeutet dies, dass es grundsätzlich unwahrscheinlich ist, dass das Objekt woanders verwendet wird, und dass das Objekt dann zu einem wiederverwertbaren Objekt wird. Diese Methode wird Referenzzählung genannt.

Diese Methode ist einfach und grob und sehr effizient. Eine hohe Effizienz führt zwangsläufig zu einigen Problemen, selbst wenn Sie dem Objekt Null zuweisen, kann dieser Algorithmus immer noch nicht recycelt werden. Schauen Sie sich den folgenden Code an

public class GcTest {public Object object = null;    public static void main(String[] args) {
        
        GcTest gcTest1 = new GcTest();
        GcTest gcTest2 = new GcTest();
        
        gcTest1.object = gcTest1;
        gcTest2.object = gcTest2;
        
        gcTest1 = null;
        gcTest2 = null;
    }
}
Nach dem Login kopieren

Obwohl gcTest1 und gcTest2 null sind, wird nicht mehr auf die Objekte zugegriffen, auf die sie verweisen, sondern weil sie auf jedes einzelne verweisen other , was dazu führt, dass ihre Referenzzähler alle 0 sind, dann wird der Garbage Collector sie nie zurückfordern.

Das obige Problem wurde aufgedeckt. Schauen wir uns an, wie JVM dieses Problem löst. Um dieses Problem zu lösen, wird in Java eine Methode zur Erreichbarkeitsanalyse übernommen. Die Grundidee dieser Methode besteht darin, eine Reihe von „GC Roots“-Objekten als Ausgangspunkt zu durchsuchen. Wenn zwischen „GC Roots“ und einem Objekt kein erreichbarer Pfad vorhanden ist, wird das Objekt jedoch als nicht erreichbar bezeichnet. Es ist zu beachten, dass Objekte, die als nicht erreichbar eingestuft werden, nicht unbedingt zu wiederverwertbaren Objekten werden. Ein als unerreichbar eingestufter Gegenstand muss mindestens zwei Markierungsprozesse durchlaufen, um zu einem wiederverwertbaren Gegenstand zu werden. Wenn während dieser beiden Markierungsprozesse immer noch keine Möglichkeit besteht, zu entkommen und zu einem wiederverwertbaren Gegenstand zu werden, wird er grundsätzlich zu einem wiederverwertbaren Gegenstand. . Das „Vertiefte Verständnis von JVM“ erklärt es sehr ausführlich. Der Autor stellt das Konzept von GC Roots kurz vor. Wenn Sie mehr darüber erfahren möchten, können Sie das vom Autor vorgestellte Buch lesen.

Die folgenden drei Arten von Objekten werden als GC-Wurzeln in JVM verwendet, um zu bestimmen, ob ein Objekt recycelt werden kann (normalerweise müssen wir nur den Stapel der virtuellen Maschine und statische Referenzen kennen)

1. Objekte, auf die im Stapel der virtuellen Maschine (JVM-Stack) verwiesen wird (genauer gesagt, Stapelrahmen im Stapel der virtuellen Maschine). Wir wissen, dass die JVM bei der Ausführung jeder Methode einen entsprechenden Stapelrahmen erstellt (der Stapelrahmen enthält Verweise auf den Operandenstapel, die lokale Variablentabelle und den Laufzeitkonstantenpool. Der Stapelrahmen enthält alle in der Methode verwendeten Informationen). Die Referenz des Objekts (und natürlich andere grundlegende Typdaten) wird beim Ausführen der Methode aus dem Stapel der virtuellen Maschine entfernt. Auf diese Weise ist die Referenz des vorübergehend erstellten Objekts nicht mehr vorhanden Es wird keine GC-Wurzeln geben, die auf diese temporären Objekte verweisen, und diese Objekte werden beim nächsten GC wiederverwendet

 2. Objekte, auf die durch statische Klassenattribute im Methodenbereich verwiesen wird. Statische Eigenschaften sind Eigenschaften dieses Typs (Klasse) und gehören keiner Instanz allein an, daher dient diese Eigenschaft natürlich als GC-Wurzel. Solange diese Klasse existiert, existiert auch das Objekt, auf das diese Referenz verweist. Die Klasse wird ebenfalls recycelt, was später erläutert wird

3. Vom Native Stack referenzierte Objekte (Native Stack)

Das Folgende ist eine Einführung in Weiche Referenzen (softReference) und schwache Referenzobjekte (weakReference) werden durch Garbage Collection verarbeitet

String str = new String("hello");//A
SoftReference<String> sr = new SoftReference<String>(new String("java"));//B
WeakReference<String> wr = new WeakReference<String>(new String("world"));//C
Nach dem Login kopieren

  Die Recyclingsituation der oben genannten Objekte ist wie folgt: B bestimmt das String-Objekt als wiederverwertbares Objekt, wenn nicht genügend Speicher vorhanden ist, und C bestimmt das String-Objekt unter allen Umständen als wiederverwertbares Objekt. Mit anderen Worten: Soft-Referenzen werden bei einem Speicherüberlauf (OOM) recycelt, während schwache Referenzen in jedem Fall in der nächsten Recycling-Runde recycelt werden.

Im Allgemeinen recycelt JVM diese Objekte

1. Weisen Sie explizit eine Referenz auf null zu oder verweisen Sie eine Referenz, die bereits auf ein Objekt zeigt, auf ein neues Objekt.

 2. Das Objekt, auf das der lokale Verweis zeigt.

3. Die oben erwähnte schwache Referenz.

3. Garbage-Collection-Algorithmus

Nachdem festgestellt wurde, welcher Müll recycelt werden kann, muss der Garbage Collector mit der Garbage Collection beginnen, es stellt sich jedoch die Frage, wie effizient die Garbage Collection ist. Da die Java Virtual Machine-Spezifikation nicht klar vorschreibt, wie ein Garbage Collector implementiert werden soll, können virtuelle Maschinen verschiedener Hersteller Garbage Collectors auf unterschiedliche Weise implementieren. Nehmen Sie den am häufigsten verwendeten HotShot als Beispiel, daher werden wir hier nur den Kern besprechen Ideen für mehrere gängige Garbage-Collection-Algorithmen.

1. Mark-Sweep-Algorithmus (Mark-Clear)

Dies ist der einfachste Garbage-Collection-Algorithmus. Der Grund dafür ist, dass er am einfachsten zu implementieren ist Am einfachsten zum Nachdenken anregend. Der Mark-Sweep-Algorithmus ist in zwei Phasen unterteilt: die Mark-Phase und die Clear-Phase. Die Aufgabe der Markierungsphase besteht darin, alle Objekte zu markieren, die recycelt werden müssen, und die Räumphase besteht darin, den von den markierten Objekten eingenommenen Platz wiederherzustellen. Das Diagramm stammt aus dem Internet und veranschaulicht die Speicherverteilung vor und nach der Verarbeitung des Mark-Clear-Algorithmus.

Alle Bilder unten sind simulierte Speicherblöcke. Rot ist ein unbenutzter Speicherblock, Grau ist ein Speicherblock mit zu recycelnden Objekten und Gelb ist ein lebendes Objekt.

Vor dem Recycling

Nach dem Recycling

Es ist leicht zu erkennen, dass so etwas Nachteile hat Wenn ein Objekt viel Speicher belegt, muss zu diesem Zeitpunkt eine Speicherbereinigung durchgeführt werden, um Platz für dieses große Objekt zu schaffen.

2. Kopieralgorithmus

Um die Mängel des Mark-Sweep-Algorithmus zu beheben, wurde der Kopieralgorithmus vorgeschlagen. Es teilt den verfügbaren Speicher je nach Kapazität in zwei gleich große Blöcke auf und nutzt jeweils nur einen davon. Wenn dieser Speicherblock erschöpft ist, kopieren Sie die verbleibenden Objekte in einen anderen Block und bereinigen Sie dann sofort den verwendeten Speicherplatz, damit das Problem der Speicherfragmentierung weniger wahrscheinlich auftritt.

Vor dem Recycling

Nach dem Recycling

Der Kopieralgorithmus gibt im Voraus allgemeinen Speicher frei Während der Speicherbereinigung werden die verbleibenden Objekte in die andere Hälfte des Speichers verschoben. Obwohl der Speicher nicht fragmentiert ist, sind die Kosten zu hoch.

3. Mark-Compact-Algorithmus (Mark-Compact)

Um die Mängel des Kopieralgorithmus zu beheben und den Speicherplatz voll auszunutzen, wurde der Mark-Compact-Algorithmus vorgeschlagen. Die Markierungsphase dieses Algorithmus ist dieselbe wie bei Mark-Sweep, aber nach Abschluss der Markierung werden die wiederverwertbaren Objekte nicht direkt bereinigt, sondern die überlebenden Objekte an ein Ende verschoben und dann der Speicher außerhalb der Endgrenze bereinigt. Der spezifische Prozess ist in der folgenden Abbildung dargestellt:

Vor dem Recycling

Nach dem Recycling

4. Generationssammlungsalgorithmus (Generationssammlungsalgorithmus)

Der Generationssammlungsalgorithmus ist der Algorithmus, der derzeit von den meisten JVM-Garbage Collectors verwendet wird. Die Kernidee besteht darin, den Speicher entsprechend dem Lebenszyklus des Objekts in mehrere unterschiedliche Bereiche zu unterteilen. Unter normalen Umständen ist der Heap-Bereich in die Tenured Generation und die Young Generation unterteilt. Das Merkmal der Old Generation besteht darin, dass bei jeder Müllsammlung nur eine kleine Anzahl von Objekten recycelt werden muss und nicht alle Objekte recycelt werden müssen. Die Merkmale der jungen Generation sind: Bei jeder Speicherbereinigung muss eine große Anzahl von Objekten recycelt werden, sodass der am besten geeignete Sammelalgorithmus entsprechend den Merkmalen verschiedener Generationen übernommen werden kann. Sie können die Methode System.gc() aufrufen, um die Recyclingsituation zu überprüfen.

Derzeit übernehmen die meisten Garbage Collectors den Kopieralgorithmus für die neue Generation, da die meisten Objekte in jeder Garbage Collection der neuen Generation recycelt werden müssen, was bedeutet, dass die Anzahl der Kopiervorgänge geringer ist, in der Praxis jedoch nicht Basierend auf dem Verhältnis 1:1 wird der Raum der neuen Generation im Allgemeinen in einen größeren Eden-Raum und zwei kleinere Survivor-Räume aufgeteilt Kopieren Sie beim Recycling die überlebenden Objekte in Eden und Survivor in einen anderen Survivor-Bereich und bereinigen Sie dann Eden und den gerade verwendeten Survivor-Bereich.

Da das Merkmal der alten Generation darin besteht, dass jedes Mal nur eine kleine Anzahl von Objekten recycelt wird, wird im Allgemeinen der Mark-Compact-Algorithmus verwendet.

Beachten Sie, dass es außerhalb des Heap-Bereichs eine weitere Generation gibt, nämlich die permanente Generation (Permanet-Generation), die zum Speichern von Klassen, Konstanten, Methodenbeschreibungen usw. verwendet wird. Beim Recycling der permanenten Generation werden hauptsächlich zwei Teile recycelt: verlassene Konstanten und nutzlose Klassen.

3. Typischer Garbage Collector

Das Folgende sind einige wahrscheinlichkeitstheoretische Dinge, die der Autor nicht verstehen kann, deshalb habe ich sie einfach hierher verschoben und mit Ihnen geteilt

1 .Serial/Serial Old

Der Serial/Serial Old-Collector ist der einfachste und älteste Collector. Es handelt sich um einen Single-Threaded-Collector, und wenn er die Garbage Collection durchführt, müssen alle Benutzer-Threads angehalten werden. Der Serial Collector ist ein Collector für die neue Generation und verwendet den Copying-Algorithmus. Der Serial Old Collector ist ein Collector für die alte Generation und verwendet den Mark-Compact-Algorithmus. Der Vorteil besteht darin, dass es einfach und effizient zu implementieren ist, der Nachteil besteht jedoch darin, dass es für Benutzer zu Pausen führt.

2.ParNew

Der ParNew-Kollektor ist eine Multithread-Version des Serial-Kollektors, der mehrere Threads für die Speicherbereinigung verwendet.

3.Parallel Scavenge

Der Parallel Scavenge-Kollektor ist ein Multithread-Kollektor der neuen Generation (Parallel-Kollektor). Er muss andere Benutzer-Threads während des Recyclings nicht anhalten. Dieser Kollektor unterscheidet sich von den beiden vorherigen Kollektoren hauptsächlich darin, einen kontrollierbaren Durchsatz zu erreichen.

4.Parallel Old

Parallel Old ist die alte Generation des Parallel Scavenge Collectors (Parallel Collector), der Multithreading und Mark-Compact-Algorithmus verwendet.

5.CMS

Der CMS-Kollektor (Current Mark Sweep) ist ein Kollektor, der darauf abzielt, die kürzeste Recycling-Pausezeit zu erreichen. Es handelt sich um einen gleichzeitigen Kollektor, der den Mark-Sweep-Algorithmus verwendet.

6.G1

Der G1-Kollektor ist heute die modernste Entwicklung der Kollektortechnologie. Er ist ein Kollektor für serverseitige Anwendungen und kann Multi-CPU- und Multi-CPU-Anwendungen voll ausnutzen -Kernumgebungen. Es handelt sich also um einen parallelen und gleichzeitigen Kollektor, der vorhersehbare Pausenzeiten modelliert.

4. Zusammenfassung und Ergänzungen

Im Allgemeinen wird die Speicherzuordnung von Objekten auf dem Heap zugewiesen. Objekte werden hauptsächlich im Eden Space und From Space der neuen Generation zugewiesen Fälle, direkt in der alten Generation zugeordnet. Wenn der Platz von Eden Space und From Space in der neuen Generation nicht ausreicht, wird ein GC eingeleitet. Wenn Eden Space und From Space das Objekt nach GC aufnehmen können, wird es im Eden Space und From Space platziert. Während des GC-Prozesses werden die überlebenden Objekte in Eden Space und From Space nach To Space verschoben und anschließend Eden Space und From Space bereinigt. Wenn während des Bereinigungsvorgangs nicht genügend Speicherplatz zum Speichern eines Objekts vorhanden ist, wird das Objekt in die alte Generation verschoben. Nachdem GC durchgeführt wurde, werden Eden Space und To Space verwendet. Die überlebenden Objekte werden während des nächsten GC nach From Space kopiert und der Zyklus wiederholt sich. Wenn ein Objekt einem GC im Survivor-Bereich entkommt, wird sein Objektalter um 1 erhöht. Wenn das Objektalter 15 Jahre erreicht, wird es standardmäßig in die alte Generation verschoben.

Im Allgemeinen werden große Objekte direkt der alten Generation zugeordnet. Die sogenannten großen Objekte beziehen sich auf Objekte, die viel kontinuierlichen Speicherplatz benötigen. Das häufigste große Objekt ist ein großes Array, z als:

byte[] data = new byte[4*1024*1024]

Dadurch wird normalerweise Speicherplatz direkt in der alten Generation zugewiesen.

Natürlich sind die Zuordnungsregeln nicht zu 100 % festgelegt. Dies hängt davon ab, welche Garbage-Collector-Kombination und JVM-bezogene Parameter derzeit verwendet werden.

Das obige ist der detaillierte Inhalt vonWas ist der Java-Garbage-Collection-Mechanismus?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage