WeakReference

Schonmal jmd verwendet?
Haben die irgendwelche Nachteile von denen man wissen sollte?

Besonderst im Bezug auf das klassische Creator/Destroyer Verfahren.
Hab mir überlegt einer meiner add(Object o) Methoden sowas zu verpassen damit man nicht vergisst remove( o ) auszuführen

Ich hab das mal verwendet bei einem Obersver-Pattern. Mein Obersvalbe hat all registrierten Observer als Weak reference gespeichert. Blöd war nur, dass ich an anderer Stellen den Obersver im klassischen Stil ala anonyme klasse implementiert hatte.

also

observable.addObserver(new Oberserver(){
  ...
})

Dadurch, dass der Observer nirgends eine normale Referenz hat, wurde dieser daher bei der nächsten Garbage Collection aufgeräumt. (eigentlich logisch habs aber trotzdem übersehen)

1 „Gefällt mir“

Sowas hatte ich mir schon gedacht. Im Grunde das gleiche Problem das man zu lösen versucht, man muss sich darum kümmern das etwas irgendwo referenziert wird.

Ich habe noch nie so richtig verstanden wozu man das braucht.

Der Anwendungsfall ist ja eigentlich: Daten mit fettem Memory-footprint, die ggf leicht wiederbeschafft werden können. Aber irgendwie klingt das für mich nach 'nem Widerspruch…

bye
TT

Ich glaube das sprichst du eher SoftReferences an, die in den Müll kommen wenn der Systemspeicher ein bisschen knapp wird.

Mein Anwendungsfall wäre (oder dann jetzt auch ist) eine Physikberechnung.
Man hat auf der einen Seite eine Physikengine und auf der anderen Seite sein eigenes separates Programm. Die Beiden Programmteile miteinander zu verknüpfen ist sehr schwierig.
Entsprechend gibt es ein eigen erstelltes Objekt im eigenen Programm und ein Schwester-Physikobjekt in der Physikengine.

Wird das Schwesterobjekt gelöscht dann soll sich der GC um die anderen evt. Geschwister kümmern ohne dass man manuell irgendwo remove() auslösen muss, das aber vergisst und dadurch ein Memory Leak entsteht.

Soweit ich weiß, wird das intern von WeakHashMap verwendet. Damit kann man eigentlich nur sicher stellen, dass Objekte (OBJ_A), die eigentlich nur wegen dem Objekt (OBJ_B) hinter der WeakReference existieren. Wenn OBJ_B im Programm nirgendwo mehr referenziert ist, wird OBJ_A ja auch nicht mehr benötigt.
Mit der WeakHashMap kann man z.B. URLs auf geladene Bilder mappen, damit diese nur einmal geladen werden müssen. Wenn ein solches Bild im Programmverlauf nicht mehr referenziert ist, verschwindet auch die URL aus der Map. Bei einer normalen Map sind die Bilder darin normal referenziert - diese Referenz bleibt dann immer als letztes übrig und hindert GC daran, die Resourcen dafür freizugeben.
Wenn man selber was mit WeakReference implementieren will, kann man sich den Mechanismus im Quellcode der WeakHashMap ja mal ansehen.

Ich wollte schon ab und zu mal was mit WeakReferences machen (hauptsächlich was laden von Bildern usw. angeht) allerdings ist mir nie wirklich klar geworden wie das funktioniert, da ich ja über get() wieder was kriege, was das aufräumen verhindert. Jedenfalls dachte ich das bisher immer… vllt hab ich da immer was falsch gesehen

WeakReferences brauchst du um Speicherlöcher zu verhindern. Und eines zu produzieren ist mit JavaFX denkbar einfach. Stell dir vor du hast eine Pagination und jede Seite wird neu aufgebaut beim wechseln der Seite. Jetzt registriert sich das ViewModel als Listener auf einem SingletonService. Diese Referenz (welche der Service hält) sorgt dafür, dass deine Objekte bis ins Unendliche wachsen. Kann schnell sehr teuer werden, da das ViewModel ja auch die View fest hält. Letztendlich hast du hier 2 Möglichkeiten:

  1. Einen Mechanismus einbauen zum selber aufzuräumen
  2. WeakReference

Und die WeakReference ist deutlich eleganter und ist mit weniger Aufwand realisierbar. (Btw: Wenn du mit JavaFX arbeitest verwendest du generell sehr viel WeakReferences - den jedes binding davon beruht auf diesem Konzept)

Nun ja, das was dir get zurück liefert solltest du halt besser nicht in einem Feld ablegen. Solange du nur in einem lokalen Methoden-Scope damit arbeitest ist alles ok.

Okay, also ein weiterer Nachteil (den ich bereits vorher kannte) ist das Aufräumen. Klar die WeakReference oder PhantomReference Objekte werden nicht automatisch aus der Liste/Container entfernt.
Stattdessen muss man eine weitere Liste beim GC registrieren bei dem der GC die entfernten Objekte derren Referenzen ablegen kann und dann muss man sie selber aufräumen.

Nur wann und wo? :sweat_smile:
Im Grunde wenn bei meiner Klasse gerade etwas gemacht wird und damit ein Thread „gerade Zeit hat“. Das erzeugt aber sicherlich unerwünschten Overhead.
Auf der anderen Seite ist ein anstreben von weniger oder garkeiner GC sowieso vorteilhaft, es ist leider nicht egal, und das würde dieses bestreben mehr gewichten.

Nein musst du nicht, denn wenn die Weak reference auf ein get() mit null antwortet, weist du auch, dass das Object garbage collected wurde. Also würde es reichen, dass du wenn du null als antwort erhältst das WaekReference-Objekt aus der Liste wieder entfernst. Also ob du zwingend die Reference Queue beim anlegen der WeakRefernce brauchst oder nicht hängt stark vom Usecase ab.

Bzg. der PhantomReference vl findest du einen realistischen fall wo man soetwas braucht, mir ist noch keiner eingefallen, da es bereits für WeakReferencen schwierig ist einen wirklich brauchbaren Usecase zu finden.