Dieser Artikel enthält hauptsächlich eine detaillierte Erklärung des Java-Garbage-Collection-Mechanismus und relevante Informationen zu Beispielcode. Freunde, die ihn benötigen, können sich auf
Detaillierte Erklärung des Java-Garbage-Collection-Mechanismus
Auf den ersten Blick sollte die Müllabfuhr genau das tun, was ihr Name vermuten lässt: Müll finden und entfernen. Tatsächlich ist es genau das Gegenteil. Die Garbage Collection verfolgt alle Objekte, die noch verwendet werden, und markiert die verbleibenden Objekte als Müll. Schauen wir uns vor diesem Hintergrund genauer an, wie dieses automatisierte Speicherrecycling namens „Garbage Collection“ in der JVM implementiert wird.Manuelle Speicherverwaltung
Bevor wir die moderne Version der Speicherbereinigung einführen, werfen wir einen kurzen Blick auf die Tage, als Speicher explizit manuell zugewiesen und freigegeben werden musste. Wenn Sie vergessen, den Speicher freizugeben, kann dieser Speicher nicht wiederverwendet werden. Dieser Speicher ist belegt, wird aber nicht genutzt. Dieses Szenario wird als Speicherverlust bezeichnet. Das Folgende ist ein einfaches Beispiel für die manuelle Speicherverwaltung, geschrieben in C:int send_request() { size_t n = read_size(); int *elements = malloc(n * sizeof(int)); if(read_elements(n, elements) < n) { // elements not freed! return -1; } // … free(elements) return 0; }
Intelligente Zeiger
Eine frühe Implementierung der automatischen Garbage Collection ist die Referenzzählung. Sie wissen, wie oft auf jedes Objekt verwiesen wurde. Wenn der Zähler 0 erreicht, kann das Objekt sicher recycelt werden. Der Shared Pointer von C++ ist ein sehr bekanntes Beispiel:int send_request() { size_t n = read_size(); stared_ptr<vector<int>> elements = make_shared<vector<int>>(); if(read_elements(n, elements) < n) { return -1; } return 0; }
Automatische Speicherverwaltung
Im obigen C++-Code müssen wir auch explizit angeben, dass wir die Speicherverwaltung verwenden müssen. Was würde also passieren, wenn alle Objekte diesen Mechanismus nutzen würden? Das ist so praktisch, dass Entwickler nicht über die Bereinigung des Speichers nachdenken müssen. Die Laufzeit erkennt automatisch, welcher Speicher nicht mehr verwendet wird und gibt ihn frei. Mit anderen Worten: Der Müll wird automatisch recycelt. Der Garbage Collector der ersten Generation wurde 1959 in Lisp eingeführt und die Technologie hat sich bis heute weiterentwickelt.Referenzzählung
Die Idee, die wir gerade mit dem gemeinsamen Zeiger von C++ demonstriert haben, kann auf alle Objekte angewendet werden. Viele Sprachen wie Perl, Python und PHP verwenden diesen Ansatz. Dies lässt sich leicht mit einem Bild erklären: Die grüne Wolke stellt die im Programm noch verwendeten Objekte dar. Aus technischer Sicht ist dies ein bisschen wie eine lokale Variable in einer ausgeführten Methode oder eine statische Variable. Die Situation kann je nach Programmiersprache unterschiedlich sein, daher ist dies nicht unser Schwerpunkt. Die blauen Kreise stellen Objekte im Speicher dar, und Sie können sehen, wie viele Objekte darauf verweisen. Objekte in grauen Kreisen werden von niemandem mehr referenziert. Daher handelt es sich um Müllobjekte, die vom Garbage Collector bereinigt werden können. Sieht gut aus, oder? Ja, aber es gibt einen großen Fehler. Es ist leicht, dass einige isolierte Ringe auftauchen. Die darin enthaltenen Objekte gehören keiner Domäne an, sie verweisen jedoch aufeinander, was zu einer Referenznummer ungleich Null führt. Hier ist ein Beispiel: Wie Sie sehen können, ist der rote Teil tatsächlich ein Müllobjekt, das von der Anwendung nicht mehr verwendet wird. Aufgrund eines Fehlers bei der Referenzzählung kommt es zu einem Speicherverlust. Es gibt mehrere Möglichkeiten, dieses Problem zu lösen, z. B. die Verwendung spezieller „schwacher“ Referenzen oder die Verwendung eines speziellen Algorithmus zum Recyceln von Zirkelreferenzen. Die zuvor erwähnten Sprachen wie Perl, Python und PHP verwenden alle ähnliche Methoden zum Recyceln von Zirkelverweisen, dies würde jedoch den Rahmen dieses Artikels sprengen. Wir werden die von der JVM verwendete Methode im Detail vorstellen.Löschung markieren
Zunächst sollte die Definition der Objekterreichbarkeit durch die JVM klarer sein. Es ist nicht mehr so vage wie zuvor mit einer grünen Wolke, sondern hat eine sehr klare und spezifische Definition des Garbage Collection Roots-Objekts (Garbage Collection Roots):Verschiedene GC-Algorithmen in JVM, wie Parallel Scavenge, Parallel Mark+Copy und CMS, sind alle unterschiedliche Implementierungen dieses Algorithmus, aber jede Stufe ist konzeptionell etwas anders, sie sind immer noch gleich Entspricht zu den beiden oben genannten Schritten.
Das Wichtigste an dieser Implementierung ist, dass es keine durchgesickerten Objektschleifen mehr gibt:
Der Nachteil besteht darin, dass der Anwendungsthread angehalten werden muss, um das Recycling abzuschließen, wenn die Referenz erhalten bleibt Wenn Sie sich ändern, können Sie nicht zählen. Die Situation, in der die Anwendung angehalten wird, damit die JVM ihre Aufgaben erledigen kann, wird auch als „Stop The World Pause“ (STW) bezeichnet. Es gibt viele Möglichkeiten, diese Pause auszulösen, aber die Garbage Collection ist wahrscheinlich die häufigste.
Das Obige ist eine detaillierte Erklärung des Java-Garbage-Collection-Mechanismus und Beispielcode. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn).