Unterliegt Go denselben subtilen Speicherverlusten wie Java?

89

Hier sind die Fakten:

  • Die Sprache Go hat einen Garbage Collector.

  • Java hat eine Garbage Collection

  • Viele Java-Programme haben (subtile oder nicht) Speicherlecks

Als Beispiel für ein Java-Programm mit Speicherlecks (nicht für schwache Nerven kann die Frage Ihre Überzeugungen erschüttern) finden Sie hier ein kleines Java-Programm namens Tomcat, das sogar die Schaltfläche "Lecks suchen" hat: Gibt es einen Weg? um Speicherverluste bei der Bereitstellung in Tomcat zu vermeiden?

Ich frage mich also: Werden in Go geschriebene Programme die gleichen (subtilen oder nicht) Speicherlecks aufweisen, die einige in Java geschriebene Programme aufweisen?

SyntaxT3rr0r
quelle
29
"Viele Java-Programme haben (subtile oder nicht) Speicherlecks" Haben Sie Beweise für diese "Tatsache" oder ist es nur ein Gesprächsthema?
Peter Lawrey
17
@Webinator: Ich denke, Sie müssen ein Beispiel für einen dieser "subtilen Speicherlecks" geben, die "viele" Java-Programme haben. Wenn Sie keinen Fehler im Garbage Collector geltend machen, besteht die einzige Möglichkeit, Speicher in reinem Java zu verlieren, darin, Referenzen beizubehalten, die Sie nicht mehr verwenden, z. B. indem Sie Objekte in eine Sammlung einfügen und sie niemals aus dieser Sammlung entfernen. Wenn dies die Art von Leck ist, auf die Sie sich beziehen, schützt keine Sprache der Welt vor ihnen, einschließlich Go.
JeremyP
14
Hier sind die Speicherlecks, über die ich gesprochen habe (+200 Upvotes, Antworten mit +150 Upvotes, viele aktuelle Java-Speicherlecks erklärt): stackoverflow.com/questions/6470651/…
SyntaxT3rr0r
6
Natürlich haben JAVA-Programme Speicherlecks. Vergessen Sie einfach, einen Verweis auf null zu setzen, wenn Sie diese länger benötigen. Tritt häufig in großen persistenten Sammlungen (wie Caches) mit Beobachter-Entwurfsmustern oder lokalen Thread-Variablen auf. Dies ist nicht theoretisch, ich habe mehrere Speicherverluste selbst in der Produktion korrigiert. Und das ist kein Anti-Java. Ich bin seit mehr als 5 Jahren ein Vollzeit-JAVA-Entwickler und habe an vielen verschiedenen Projekten gearbeitet. Nicht zu erkennen, dass in JAVA (oder jeder anderen vorhandenen Sprache) ein Speicherverlust auftreten kann, ist kein Fanboyismus, sondern eher ein Mangel an Verständnis dafür, wie die Dinge wirklich funktionieren.
Nicolas Bousquet
6
Diese Frage könnte ohne das Drama und die Kommentare über "Fanboyismus", "jemandes Glauben erschüttern" und dergleichen auskommen. Esp. da die ganze Diskussion auf "meine Definition von memory leakist besser als deine" hinausläuft.
LAFK sagt Reinstate Monica

Antworten:

44

Sie verwechseln hier verschiedene Arten von Speicherlecks.

Die abscheulichen, auf expliziter Speicherverwaltung basierenden Speicherlecks sind in Java (oder einer anderen GC-basierten Sprache) verschwunden. Diese Lecks werden dadurch verursacht, dass der Zugriff auf Speicherblöcke vollständig verloren geht, ohne dass diese als nicht verwendet markiert werden.

Die "Speicherlecks", die in Java und jeder anderen Sprache auf dem Planeten noch vorhanden sind, bis der Computer unsere Gedanken lesen kann, sind immer noch bei uns und werden auf absehbare Zeit auftreten. Diese Lecks werden dadurch verursacht, dass der Code / Programmierer Verweise auf Objekte aufbewahrt, die technisch nicht mehr benötigt werden. Dies sind grundsätzlich logische Fehler, die mit aktuellen Technologien in keiner Sprache verhindert werden können.

James
quelle
23
Ein Speicherverlust tritt einfach auf, wenn Sie vergessen, Speicher freizugeben. In Java tritt dies auf, wenn Sie vergessen, Verweise auf null zu setzen. In C ++ passiert es, wenn Sie vergessen, kostenlos anzurufen. Beides sind gültige Speicherverlustfälle. Das grundlegende Problem ist dasselbe: Ihr Programm verbraucht immer mehr Speicher, bis es schließlich mit einem OutOfMemory-Fehler abstürzt.
Nicolas Bousquet
1
Es stimmt zwar, dass keine Sprache den Programmierer daran hindern kann, solche Logikfehler zu machen, aber es stimmt auch, dass einige dieser Fehler im Java SDK selbst vorhanden sind (siehe zum Beispiel, java.util.logging.Leveldas eine private Statik enthält, ArrayListin die alle diese Objekte eingebaut sind platziert auf dem Bau, und von dem sie nie entfernt werden), die es schwieriger macht , sie zu vermeiden , wenn die Java - Programmierung als in einer anderen Sprache , die nicht solche Fehler nicht enthält
Jules
7
Ich denke, das OP hat nach Speicherverlusten von Objekten gefragt, die wirklich nicht erreichbar sind, wie in der akzeptierten Antwort auf die verknüpfte Frage. Der Speicherverlust, der durch das Laden von Klassen aus Threads verursacht wird. -1
qbt937
1
Es ist auch denkbar, dass durch statische Analyse festgestellt werden kann, ob Referenzen nach ihrer Nutzungsdauer weiterhin vorhanden sind - kein Gedankenlesen erforderlich.
Kyle Strand
1
@Amrit Nein, der Garbage Collector sammelt Speicher Sie nicht Referenzen müssen mehr. Es ist nicht möglich zu wissen, ob es in Ordnung ist, etwas zu entfernen, auf das Sie noch einen Verweis haben.
Raphael Schmitz
19

Es ist sehr wahrscheinlich, dass Go-Programme Speicherlecks aufweisen. Die aktuelle Implementierung von Go verfügt über einen einfachen Mark-and-Sweep-Garbage-Collector. Dies ist nur als vorübergehende Lösung gedacht und nicht als langfristiger Garbage Collector. Weitere Informationen finden Sie auf dieser Seite . Schauen Sie unter die Überschrift Go Garbage Collector. Diese Seite enthält sogar einen Link zum Code für die aktuelle Version, wenn Sie dazu neigen.

Zeiger
quelle
1
Eines der Probleme des Markierungs- und Sweep-Sammlers in Java ist die Speicherverwaltung. Obwohl dies technisch gesehen kein Speicher ist, kann es sich um einen Speicherverlust handeln, der der Anwendung zur Verfügung steht.
Peter Lawrey
9

Ein "Speicherverlust" liegt vor, wenn ein Speicherelement, von dem der Programmierer dachte, dass es freigegeben wird, nicht freigegeben wird. Dies kann in jeder Sprache geschehen, ob Müll gesammelt wird oder nicht. Die übliche Ursache in GC-Sprachen besteht darin, einen zusätzlichen Verweis auf den Speicher beizubehalten.

"Sprachen verursachen keine Speicherlecks, Programmierer verursachen Speicherlecks".

DJClayworth
quelle
8

Garbage Collection oder nicht, Sie können ein Programm schreiben, das zum größten Teil Speicherlecks in Java, Go oder einer anderen Sprache aufweist.

Die Speicherbereinigung entlastet den Programmierer zwar etwas, verhindert jedoch Leckagen nicht vollständig.

jzd
quelle
4
Ich weiß, ich weiß. Ich spreche speziell über die subtilen Speicherlecks, die in Java existieren, selbst wenn Java zu Beginn als eine Sprache vermarktet wurde, in der dank des GC keine Speicherlecks existieren .
SyntaxT3rr0r
4
Entschuldigung, das war nicht klar. Sie sagten, "viele Java-Programme haben (subtile oder nicht) Speicherlecks".
JZD
3

Sie mischen hier Abstraktionsebenen: Die Speicherlecks sind auf Fehler in der Bibliothek zurückzuführen (bei denen Objekte aufeinander verweisen, obwohl Ketten von 'a auf b verweisen') sowie auf einen Kompromiss bei der Implementierung des Garbage Collector zwischen Effizienz und Genauigkeit. Wie viel Zeit möchten Sie für das Auffinden solcher Schleifen aufwenden? Wenn Sie doppelt so viel Zeit aufwenden, können Sie Schleifen doppelt so lange erkennen.

Das Problem mit dem Speicherverlust ist also nicht programmiersprachenspezifisch. Es gibt keinen Grund, warum GO für sich genommen besser oder schlechter als Java sein sollte.

Gulden
quelle
1
Ich stimme nicht ganz zu. Speicherlecks sind auf die Tatsache zurückzuführen, dass Java es ermöglicht, sich selbst in den Fuß zu schießen, und dass dies nicht unbedingt mit einem Bibliotheksfehler zusammenhängt. Viele Programmierer schreiben Programme, die langsam aber sicher Speicher in Java verlieren, und das ist ihre eigene Schuld, nicht die Schuld der Bibliotheken. Wenn genau der Java GC einen Kompromiss zwischen Zeit und möglichem Leck eingeht, macht Go dann die gleichen Kompromisse?
SyntaxT3rr0r
1
und die Frage ist wirklich nicht "wie viel Zeit möchte ich damit verbringen, solche Schleifen herauszufinden?" Die Frage ist "Wie viel Zeit die Spezifikationen vorschreiben, die der Go GC für solche Schleifen ausgibt " , was meiner Meinung nach eine interessante Frage ist.
SyntaxT3rr0r
16
Zyklische Referenzketten verhindern nicht die Speicherbereinigung in Java.
Andy Thomas