.Net vs. Java Garbage Collector

Lesezeit: 5 Minuten

Benutzer-Avatar
Mike

Kennt jemand die Hauptunterschiede zwischen den Java- und .Net-Garbage Collectors? Eine Websuche hat nicht viel ergeben, und es war eine Frage, die in einem Test auftauchte.

Benutzer-Avatar
ShuggyCoUk

Der Unterschied liegt zwischen der CLR (.Net) GC und der JVM GC und nicht in den Sprachen selbst. Beide unterliegen Änderungen und die Spezifikation ihres Verhaltens ist lose, damit dies geändert werden kann, ohne dass dies die Korrektheit von Programmen beeinträchtigt.

Es gibt einige historische Unterschiede, die hauptsächlich darauf zurückzuführen sind, dass .Net mit Lehren aus der Entwicklung von Java (und anderen gc-basierten Plattformen) entwickelt wurde. Gehen Sie im Folgenden nicht davon aus, dass das .Net-System in irgendeiner Weise überlegen war, weil es von Anfang an Funktionalität enthielt, es ist einfach das Ergebnis eines späteren Kommens.

Ein bemerkenswerter, öffentlich sichtbarer Unterschied besteht darin, dass MS GC seine Generationsnatur (über die GC-API) offenlegt. Dies wird wahrscheinlich noch einige Zeit so bleiben, da dies aufgrund des Verhaltens der meisten Programme ein offensichtlicher Ansatz ist: Die meisten Zuweisungen sind extrem kurzlebig.

Anfängliche JVMs hatten keine generationsübergreifenden Garbage Collectors, obwohl diese Funktion schnell hinzugefügt wurde. Die erste Generation von Kollektoren implementiert von SonneOracle und andere waren eher Mark and Sweep. Es wurde erkannt, dass ein Mark-Sweep-Compact-Ansatz zu einer viel besseren Speicherlokalität führen würde, was den zusätzlichen Kopieraufwand rechtfertigt. Die CLR-Laufzeitumgebung debütierte mit diesem Verhalten.

Ein Unterschied zwischen SonneDie GC-Implementierung „Ethos“ von Oracle und Microsoft steht für Konfigurierbarkeit.

Sonnebietet eine große Anzahl von Optionen (auf der Befehlszeile), um Aspekte des GC zu optimieren oder zwischen verschiedenen Modi umzuschalten. Viele Optionen haben das Zeichen -X oder -XX, um anzuzeigen, dass sie von verschiedenen Versionen oder Anbietern nicht unterstützt werden. Im Gegensatz dazu bietet die CLR so gut wie keine Konfigurierbarkeit; Ihre einzige wirkliche Option ist die Verwendung der Server- oder Client-Sammler, die jeweils für Durchsatz und Latenz optimiert sind.

In beiden Unternehmen (und in Open-Source-Implementierungen) wird aktiv an GC-Strategien geforscht. Die aktuellen Ansätze, die in den neuesten GC-Implementierungen verwendet werden, beziehen sich ebenfalls auf Eden-Bereiche pro Thread (Verbesserung der Lokalität und Ermöglichung, dass die Eden-Sammlung möglicherweise keine vollständige Pause verursacht). als Pre-Tenuring-Ansätze, die versuchen, bestimmte Allokationen in der Eden-Generation zu vermeiden.

  • Sehr gute Antwort. Nur die Fakten – den Religionskrieg netterweise vermeidend.

    – serg10

    30. Januar 2009 um 13:09 Uhr

  • möchte die -1 einen Grund hinzufügen?

    – ShuggyCoUk

    31. Mai 2010 um 21:33 Uhr

  • Es ist erwähnenswert, dass “normales” .net eine Technik namens “Write Fence” verwendet, um zu verfolgen, welche Objekte geschrieben wurden, seit sie das letzte Mal hochgestuft wurden. Soweit ich weiß, kann ein Objekt, das zB von gen0 auf gen1 befördert wurde und seitdem nicht mehr geschrieben wurde, möglicherweise keine Verweise auf gen0-Objekte enthalten. Während einer gen0-Sammlung besteht keine Notwendigkeit, darin enthaltene Referenzen zu untersuchen, da die einzigen Objekte, auf die sie verweist, sowieso als “lebendig” angesehen werden. Das Überspringen nicht geschriebener gen1/gen2-Objekte während einer gen0-Sammlung ist ein großer Gewinn.

    – Superkatze

    23. November 2012 um 23:28 Uhr


  • @supercat Ich würde erwarten, dass die meisten (alle?) Java-Generations-GCs dieselbe Technik verwenden, um ehrlich zu sein, ich kann keine Funktion von Java sehen, die die Verwendung ausschließen würde.

    – ShuggyCoUk

    28. November 2012 um 15:29 Uhr

  • @ShuggyCoUk: Ich glaube, einige tun dies, wäre aber nicht überrascht, wenn einige dies nicht tun, da Schreibzäune nicht kostenlos sind und da Generations-GC bieten kann etwas Vorteil, zu sehr niedrigen Kosten, ohne sie. Wenn ich ein Framework entwerfen würde, würde ich ein Mittel bereitstellen, um anzugeben, dass bestimmte Klassen unveränderlich sind (einschließlich eines unveränderlichen Array-Typs); Sogar Implementierungen, die Schreibzäune nicht unterstützten, könnten davon profitieren, zu wissen, dass ein unveränderliches gen1-Objekt keine Verweise auf gen0-Objekte enthalten würde.

    – Superkatze

    28. November 2012 um 17:38 Uhr

Benutzer-Avatar
Brian Rasmussen

Dies ist nur eine Ergänzung zu ShuggyCoUks ausgezeichneter Antwort. Der .NET GC verwendet auch den sogenannten Large Object Heap (LOH). Die CLR ordnet vorab eine Reihe von Objekten auf dem LOH zu, und alle vom Benutzer zugeordneten Objekte mit mindestens 85000 Byte werden ebenfalls auf dem LOH zugeordnet. Außerdem, double[] 1000 Elemente oder mehr werden aufgrund einiger interner Optimierungen auch auf dem LOH zugewiesen.

Der LOH wird auf verschiedene Weise anders gehandhabt als die Generationenhaufen:

  • Es wird nur während einer vollständigen Sammlung gereinigt und niemals wie die Generationenhaufen verdichtet.
  • Die Zuordnung aus dem LOH erfolgt ähnlich wie über eine freie Liste malloc wird in der C-Laufzeit verarbeitet, während Zuweisungen aus dem Generations-Heap im Wesentlichen durch einfaches Bewegen eines Zeigers in Generation 0 erfolgen.

Ich weiß nicht, ob die JVM etwas Ähnliches hat, aber es sind wichtige Informationen darüber, wie Speicher in .NET gehandhabt wird. Hoffentlich finden Sie es nützlich.

  • Guter Punkt. Wird es als guter Stil angesehen, die Erweiterungen anderer mit einer Bearbeitung in Ihre eigene Antwort zu integrieren. Wenn ja, sollten Sie dies inline oder über einen Kommentar gutschreiben?

    – ShuggyCoUk

    31. Januar 2009 um 16:54 Uhr

  • Jetzt gibt es eine Option zum Komprimieren von LOH, die standardmäßig deaktiviert ist.

    – TakeMeAsAGuest

    26. Februar 2019 um 14:23 Uhr


  • Die Option zum Komprimieren ist “einmal komprimieren”. Sie schalten es ein und die nächste blockierende Gen2-Sammlung komprimiert den LOH. Nach dem Komprimieren wird die Option auf Aus/Standard zurückgesetzt.

    – Flydog57

    5. August 2021 um 21:55 Uhr

Wenn ich mich richtig erinnere, gibt die JVM keinen freigegebenen Speicher an das Betriebssystem zurück, wie es die CLR tut.

  • Dies ist einer der auffälligeren Unterschiede.

    – Cecil hat einen Namen

    18. September 2009 um 19:24 Uhr

Java 5 führte viele Änderungen in seine GC-Algorithmen ein.

Ich bin kein C#-Experte, aber diese beiden Artikel deuten darauf hin, dass sich beide weg von einfachem Mark and Sweep und hin zu Modellen der neueren Generation entwickelt haben:

http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html
http://www.csharphelp.com/archives2/archive297.html

Ich habe das gefunden:

In der J2SE-Plattformversion 1.4.2 gab es vier Garbage Collectors, aus denen ausgewählt werden konnte, aber ohne explizite Auswahl durch den Benutzer wurde immer der serielle Garbage Collector ausgewählt. In Version 5.0 basiert die Auswahl des Kollektors auf der Klasse der Maschine, auf der die Anwendung gestartet wird.

hier und das

Ebenso wie die JVM die Zerstörung von Objekten verwaltet, tut dies auch die CLR über einen Mark-and-Compact-Garbage-Collection-Algorithmus

hier

Ich hoffe das hilft…

1130320cookie-check.Net vs. Java Garbage Collector

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy