2009-10-28 16 views
15

Ich bin kürzlich auf einen Teil des Java-Codes mit WeakReferences gestoßen - ich hatte sie noch nie im Einsatz gesehen, obwohl ich sie bei der Einführung gefunden hatte. Ist das etwas, das routinemäßig verwendet werden sollte oder nur wenn man auf Speicherprobleme stößt? Wenn letzteres möglich ist, können sie leicht nachgerüstet werden oder muss der Code ernsthaft überarbeitet werden? Kann der durchschnittliche Java (oder C#) Programmierer sie generell ignorieren?Wann sollten schwache Referenzen verwendet werden?

EDIT Kann ein Schaden von über-enthusiastischen Einsatz von WRs getan werden?

+0

Weitere Beispiele für Verwendungen für schwache Referenzen finden Sie unter http://stackoverflow.com/questions/1434156/other-uses-of-weak-references –

+0

Soweit ich weiß, ist die einzige Gefahr mit WR, dass Sie wirklich wollen eine * starke * Referenz. Wenn Ihre Objekte zu verschwinden beginnen, wenn Sie nicht möchten, dass Sie zu weit gegangen sind;) –

+0

Sie müssen wissen, wann sie und wie verwendet werden, und in einigen Fällen kommt es zu ähnlichen Problemen wie beim Multithreading mit Locking on Daten. Zum Beispiel ist es einfach falsch zu einem (.NET-Beispiel): 'if (x.IsAlive) {x.Target.ToString(); } 'weil das Objekt in der Zwischenzeit möglicherweise gesammelt wurde. Sie müssen zuerst eine starke Referenz erfassen und dann überprüfen, ob sie noch lebt: 'Objekt t = x.Target; if (t! = null) {t.ToString(); }, denn sobald Sie eine starke Referenz auf das Objekt wiedererlangt haben, wird es nicht gesammelt. – Lucero

Antwort

20

Schwache Referenzen sind alles über Garbage Collection. Ein Standard Objekt wird nicht "verschwinden", bis alle Verweise darauf getrennt sind. Dies bedeutet, dass alle Verweise, die Ihre verschiedenen Objekte darauf haben, entfernt werden müssen, bevor die Garbage Collection es als Müll betrachtet.

Mit einer schwachen Referenz, nur weil Ihr Objekt von anderen Objekten referenziert wird, bedeutet nicht unbedingt, dass es nicht Müll ist. Es kann immer noch von GC abgeholt und aus dem Speicher entfernt werden.

Ein Beispiel: Wenn ich eine Menge Foo-Objekte in meiner Anwendung habe, möchte ich vielleicht ein Set verwenden, um alle Foo's, die ich habe, zentral zu verwalten. Aber wenn andere Teile meiner Anwendung ein Foo-Objekt entfernen, indem Sie alle Verweise darauf löschen, möchte ich nicht die verbleibende Referenz, die mein Set für dieses Objekt enthält, um zu verhindern, dass es Garbage Collected wird! Wirklich, ich will nur, dass es von meinem Set verschwindet. Hier würden Sie etwas wie ein schwaches Set verwenden (Java verfügt über eine WeakHashMap), das schwache Referenzen auf seine Member anstelle von "starken" Referenzen verwendet.

Wenn Ihre Objekte nicht zu Garbage Collected gesammelt werden, wenn Sie möchten, haben Sie einen Fehler in Ihrer Buchhaltung, etwas hält immer noch eine Referenz, die Sie vergessen zu entfernen. Die Verwendung schwacher Referenzen kann den Schmerz einer solchen Buchführung mildern, da Sie sich keine Sorgen darüber machen müssen, ob ein Objekt "lebendig" und nicht müllbeseitigt bleibt, aber Sie haben nicht, um sie zu verwenden.

15

Sie verwenden sie immer dann, wenn Sie einen Verweis auf ein Objekt haben möchten, ohne das Objekt selbst am Leben zu erhalten. Dies gilt für viele Caching-ähnliche Features, spielt aber auch eine wichtige Rolle bei der Ereignisbehandlung, bei der ein Abonnent nicht am Leben gehalten werden sollte, indem er ein Ereignis abonniert.

Ein kleines Beispiel: Ein Timer-Ereignis, das einige Daten aktualisiert. Eine beliebige Anzahl von Objekten kann den Timer abonnieren, um benachrichtigt zu werden, aber die bloße Tatsache, dass sie den Timer abonniert haben, sollte sie nicht am Leben erhalten. Daher sollte der Timer schwache Referenzen auf die Objekte haben.

+1

Die Verwendung von schwachen Referenzen (insbesondere durch 'WeakHashMap') kann furchtbar schief gehen. Zum Beispiel bemerkt die VM möglicherweise, dass sie die Referenzen fast unmittelbar nach ihrer Erstellung löschen kann. Dies geschieht zwar normalerweise, nachdem die Anwendung eine Weile ausgeführt wurde. –

+1

Tackline - Ich bin mir nicht sicher 'schrecklich falsch' - sicherlich, wenn sie verwendet werden, wenn sie nicht sein sollten, dann wird die App fehlschlagen - aber das ist ein Design-Problem, nichts mit schwachen Referenzen per se zu tun –

+0

I Ich sage nicht, dass du ein Objekt nur durch eine schwache Referenz referenzieren solltest, sondern dass du diese verwenden kannst, um Verweise auf Objekte zu halten, bei denen es nicht deine Verantwortung ist, sie am Leben zu erhalten. Normalerweise sind diese Objekte Teil eines stark referenzierten Objektgraphen, aber wenn dieser Graph den Rahmen sprengt, sollte die schwache Referenz den GC nicht daran hindern, diese zu sammeln. Es ist immer das Gleiche: Verwenden Sie die geeigneten Tools, wo sie passen. – Lucero

7

Kann ein Schaden durch übermäßige Verwendung von WRs verursacht werden?

Ja kann es.

Ein Problem ist, dass schwache Referenzen Ihren Code komplizierter und potenziell fehleranfällig machen. Jeder Code, der eine schwache Referenz verwendet, muss sich mit der Möglichkeit auseinandersetzen, dass die Referenz bei jeder Verwendung unterbrochen wurde. Wenn Sie schwache Referenzen zu oft verwenden, schreiben Sie viel zusätzlichen Code. (Sie können dies abschwächen, indem Sie jede schwache Referenz hinter einer Methode verbergen, die sich um die Überprüfung kümmert, und das verworfene Objekt bei Bedarf neu erstellt. Dies muss jedoch nicht unbedingt so einfach sein, zB wenn der Neuschöpfungsprozess ein Netzwerk umfasst Zugang, müssen Sie mit der Möglichkeit der Neuerstellung Fehler zu bewältigen.)

Eine zweite Sorge ist, dass es Laufzeit Overhead mit schwachen Referenzen sind.Die offensichtlichen Kosten sind die, schwache Referenzen zu erzeugen und get auf ihnen zu benennen. Ein weniger offensichtlicher Kostenaufwand besteht darin, dass bei jeder Ausführung des GC ein erheblicher Mehraufwand erforderlich ist.

Eine letzte Sorge ist, dass wenn Sie eine schwache Referenzen für etwas verwenden, die Ihre Anwendung mit hoher Wahrscheinlichkeit in der Zukunft benötigen wird, können Sie die Kosten für die wiederholte Neuerstellung übernehmen. Wenn diese Kosten hoch sind (in Bezug auf CPU-Zeit, E/A-Bandbreite, Netzwerkverkehr, was auch immer), kann Ihre Anwendung als Ergebnis schlecht arbeiten. Es kann besser sein, der JVM mehr Speicher zu geben und keine schwachen Referenzen zu verwenden.

Natürlich bedeutet dies nicht, dass Sie die Verwendung von schwachen Referenzen vollständig vermeiden sollten. Nur dass du sorgfältig nachdenken musst. Und wahrscheinlich sollten Sie zuerst einen Speicherprofiler auf Ihrer Anwendung ausführen, um herauszufinden, woher Ihre Speicherauslastungsprobleme stammen.

1

Eine gute Frage bei der Verwendung einer WeakReference ist, wie man sich fühlen würde, wenn die schwache Referenz in dem Moment ungültig wäre, in dem keine starken Referenzen auf das Objekt existierten. Wenn dies die WeakReference weniger nützlich machen würde, dann ist WeakReference wahrscheinlich nicht die beste Lösung. Wenn dies eine Verbesserung gegenüber der nicht-deterministischen Ungültigmachung ist, die von der Speicherbereinigung herrührt, dann ist eine WeakReference wahrscheinlich die richtige Wahl.

Verwandte Themen