Was ich Ihnen im Folgenden mitteilen werde, ist der grundlegendste Algorithmus im GC-Algorithmus: Markieren/Löschen-Algorithmus. Wenn Sie diesen Algorithmus herausfinden, werden die nächsten beiden ein Kinderspiel sein.
Erinnern wir uns zunächst an den im vorherigen Kapitel erwähnten Root-Suchalgorithmus. Er kann das Problem lösen, welche Objekte wir recyceln sollten, aber er kann offensichtlich nicht die schwere Verantwortung der Speicherbereinigung tragen, da wir uns im Programm befinden (. Das Programm bezieht sich auch auf uns. Wenn Sie während des Betriebs eines JAVA-Programms, das auf der JVM ausgeführt wird, eine Speicherbereinigung durchführen möchten, muss der GC-Thread mit den Threads im Programm zusammenarbeiten, damit der Müll erfolgreich recycelt werden kann, ohne die Ausführung zu beeinträchtigen des Programms.
Um dieses Ziel zu erreichen, wurde der Mark/Clear-Algorithmus entwickelt. Wenn der verfügbare Speicherplatz im Heap erschöpft ist, stoppt es das gesamte Programm (auch Stop the World genannt) und führt dann zwei Aufgaben aus: Die erste ist das Markieren und die zweite. Das Element wird gelöscht.
LZ wird im Detail erklären, was das Markieren bzw. Löschen bewirken wird.
Markierung: Der Prozess der Markierung besteht eigentlich darin, alle GC-Roots zu durchlaufen und dann alle von GC-Roots erreichbaren Objekte als lebendige Objekte zu markieren.
Löschen: Der Reinigungsprozess durchläuft alle Objekte im Heap und löscht alle nicht markierten Objekte.
Eigentlich sind diese beiden Schritte nicht besonders kompliziert und leicht zu verstehen. LZ erklärt den Markierungs-/Löschalgorithmus in Laiensprache. Wenn das Programm ausgeführt wird und der nutzbare Speicher erschöpft ist, wird der GC-Thread ausgelöst und das Programm angehalten. Anschließend werden die verbleibenden Objekte erneut markiert und schließlich alle gelöscht Entfernen Sie nicht markierte Objekte im Heap und lassen Sie das Programm dann weiterlaufen.
Unten hat LZ eine Reihe von Bildern erstellt, um den oben genannten Prozess zu beschreiben. Lassen Sie uns diesen Prozess intuitiv betrachten.
Dieses Bild stellt den Status aller Objekte während der Ausführung des Programms dar. Ihre Flag-Bits sind alle 0 (d. h. unmarkiert). Der Standardwert unten ist 0 für unmarkiert. 1 für (markiert). Unter der Annahme, dass der effektive Speicherplatz zu diesem Zeitpunkt erschöpft ist, stoppt die JVM die Anwendung, startet den GC-Thread und startet dann die Markierungsarbeit gemäß dem Root-Suchalgorithmus Das Objekt ist wie unten gezeigt.
Wie Sie sehen können, werden gemäß dem Root-Suchalgorithmus alle vom Root-Objekt aus erreichbaren Objekte als lebendige Objekte markiert. Zu diesem Zeitpunkt hat die erste Stufe der Markierung stattgefunden abgeschlossen wurde. Als nächstes wird die zweite Stufe der Bereinigung durchgeführt. Nach Abschluss der Bereinigung sind die verbleibenden Objekte und ihr Status wie in der folgenden Abbildung dargestellt.
Wie Sie sehen können, werden nicht markierte Objekte recycelt und gelöscht, während markierte Objekte bestehen bleiben und das Markierungsbit auf 0 zurückgesetzt wird. Es versteht sich von selbst, dass Sie einfach den gestoppten Programmthread aufwecken und das Programm weiterlaufen lassen müssen.
Tatsächlich ist dieser Prozess nicht kompliziert, man kann sogar sagen, dass er sehr einfach ist. Haben Sie Recht? Es gibt jedoch einen erwähnenswerten Punkt: Warum müssen wir die Ausführung des Programms stoppen?
Das ist eigentlich nicht schwer zu verstehen. Nehmen wir an, dass unser Programm und der GC-Thread zusammenlaufen.
Angenommen, wir haben gerade das Objekt ganz rechts im Bild markiert, nennen wir es vorerst A. Dadurch wird zu diesem Zeitpunkt ein neues Objekt B im Programm erstellt, und das A-Objekt kann das B-Objekt erreichen . Da jedoch das A-Objekt zu diesem Zeitpunkt markiert wurde, ist das Markierungsbit des B-Objekts zu diesem Zeitpunkt immer noch 0, da es die Markierungsphase verpasst hat. Daher wird das neue Objekt B beim nächsten Mal, wenn es darum geht, die Phase zu räumen, hart geräumt. Daher ist es nicht schwer, sich das Ergebnis vorzustellen Der GC-Thread führt dazu, dass das Programm nicht ordnungsgemäß funktioniert.
Das obige Ergebnis ist natürlich inakzeptabel. Wir haben gerade ein neues Objekt erstellt und nach einem GC wurde es plötzlich null.
Bisher wurde der Mark/Clear-Algorithmus LZ vorgestellt. Schauen wir uns seine Mängel an. Tatsächlich sind seine Mängel leicht zu verstehen.
1. Der Nachteil besteht darin, dass die Effizienz relativ gering ist (Rekursion und vollständige Durchquerung des Heap-Objekts) und die Anwendung gestoppt werden muss, was insbesondere zu einer sehr schlechten Benutzererfahrung führt für interaktive Anwendungen ist das einfach inakzeptabel. Stellen Sie sich vor: Wenn Sie auf einer Website spielen und die Website fünf Minuten pro Stunde nicht erreichbar ist, würden Sie dann trotzdem spielen?
Der zweite Hauptnachteil besteht darin, dass der auf diese Weise gelöschte freie Speicher nicht schwer zu verstehen ist. Nach dem Löschen erscheint das Speicherlayout zufällig sei chaotisch. Um dies zu bewältigen, muss die JVM eine Liste freier Speicher verwalten, was einen weiteren Mehraufwand darstellt. Darüber hinaus ist es beim Zuweisen von Array-Objekten schwierig, kontinuierlichen Speicherplatz zu finden.
Nachdem sie die Mängel gelesen hatten, mussten sich einige Affenfreunde wahrscheinlich übergeben: „Dieser Algorithmus ist also überhaupt nutzlos. Warum führt LZ dann so etwas ein?“
Affenfreunde, macht das nicht.“ Bedenken Sie, wenn ein Algorithmus Mängel aufweist, werden Experten natürlich ihr Bestes geben, um ihn zu verbessern. Die beiden Algorithmen, die wir als Nächstes vorstellen, sind beide auf der Grundlage des Mark/Clear-Algorithmus optimiert. LZ wird den spezifischen Inhalt beim nächsten Mal mit Ihnen teilen.
Damit ist dieser Austausch beendet. Ich hoffe, Sie werden durch die Lektüre etwas gewinnen, 0.0.
Das Obige ist der Inhalt der JVM-Speicherverwaltung ------ Verfeinerung des GC-Algorithmus (fünf Minuten, damit Sie den Markierungs-/Löschalgorithmus vollständig verstehen, achten Sie bitte auf PHP). Chinesische Website (www.php.cn)!