Weakreferences/PhantomReferences

Status
Nicht offen für weitere Antworten.
T

tuxedo

Gast
Hallo zusammen,

nachdem in meinem letzten Thread "Zur Laufzeit erben" das Thema etwas ausseinander gelaufen ist, hier ein neuer Thread:

Also mir gehts gerade generell um das Verständnis der Weakreference bzw. auch Phantomreferences.

Ich habe eine Klasse A, welche Referenzen zu Klasse B und C hat. In etwa so:

Code:
class A {

private B b = null;
private C c = null;

public A (B b, C c){
this.b=b;
this.c=c;
}

}

So. Klasse B und C sind im Programm (unabhängig von A, sprich Klasse D benutzt B unc C auch noch und läuft als Thread oder so) weiter verknüpft und hängen unter anderem mit Threads und Netzwerkverbindungen zusammen.

Wenn ich jetzt möchte, dass wenn Klasse A nicht mehr erreichbar ist (also nirgendwo im Code mehr benutzt wird), Klasse A aufgeräumt wird:

Macht es dann Sinn die in Klasse A internen Referenzen auf B und C in WeakReferences zu packen?

Nach gründlicher Überlegung würde ich sagen: Nein. Wenn dann müsste ich die Instanz der Klasse A selbst in eine WeakReference packen.

Kann mich da mal jemand aufklären der damit schon gearbeitet hat? Hab so langsam aber sicher nen Knoten im Hirn ...

- Alex


edit: Hintergrund ist folgender: Wenn Klasse A nicht mehr "reachable" ist, also nirgends mehr im folgenden Code benutzt wird, dann möchte ich auf irgend eine Art und Weise benachrichtigt werden (polling in einem Thread geht auch), damit ich Klasse B und C sagen kann, dass die Netzwerkverbindung beendet und die Threads heruntergefahren werden.
 

Illuvatar

Top Contributor
Wie du eigentlich schon gesagt hast:

Du musst irgendwo eine Referenz zu A in einer WeakReference machen. Die WeakReference benachrichtigt dann, sobald diese WeakReference die letzte verbleibende Referenz ist, eine ReferenceQueue darüber - die du dann selbst implementierst. An der Stelle kannst du noch auf das A-Objekt zugreifen und aufräumen (hier ist der Unterschied zur PhantomReference, da würde nicht mal mehr das gehen). Wenn du damit fertig bist, kommt A in die Mülltonne.

Edit: Ups, ist schon eine Zeit her das ich das gemacht hab... der Teil mit der ReferenceQueue war eher Quatsch, das funktioniert bisschen anders aber ich bin mir nicht mehr sicher wie... vielleicht antwortet ja noch jemand anderes ;)
 
T

tuxedo

Gast
Bei der PhantomReference müsste es so sei wie du's beschrieben hast.

Aber mir stellen sich da 2 Fragen:

1) Da Klasse A ja noch abhängigkeiten zu B und C hat wird sie wohl nicht aufgeräumt, solange diese Abhängigkeiten noch da sind, oder?

2) Wir krieg ich Klasse A in eine *Reference gedeckelt, damit man das "von aussen" nicht sieht. Hintergrund: Klasse A ist ein RemoteObjekt (wie bei RMI) und ich möchte die Sache mit der *Reference möglichst vor dem Benutzer/Entwickler verdecken so dass er sich nicht durm kümmern muss.

- Alex
 
G

Guest

Gast
alex0801 hat gesagt.:
1) Da Klasse A ja noch abhängigkeiten zu B und C hat wird sie wohl nicht aufgeräumt, solange diese Abhängigkeiten noch da sind, oder?
Die Referenzen von A zu B und C werden aufgelöst, wenn es keine Referenz zu A mehr gibt. Der ganze "Ast" ist
abgeschnitten. Der GC geht es in mindestens zwei Schritten durch. Beim ersten stellt er fest, was tatsächlich nicht
mehr referenziert wird, beim zweiten räumt er auf. Ist der Root-Knoten nicht referenziert/referenzierbar, ist auch
alles, was vom Root-Knoten referenziert wird, als nicht referenziert zu sehen, es sei dann, es wird an anderer Stelle
noch referenziert. Man muss da zwischen Erreichbarkeit von Instanzen und Gültigkeit von Referenzen unterscheiden.
Mist, ich verstehe mich selbst nicht. :lol:

alex0801 hat gesagt.:
2) Wir krieg ich Klasse A in eine *Reference gedeckelt, damit man das "von aussen" nicht sieht. Hintergrund: Klasse A ist ein RemoteObjekt (wie bei RMI) und ich möchte die Sache mit der *Reference möglichst vor dem Benutzer/Entwickler verdecken so dass er sich nicht durm kümmern muss.
Mit einem Proxy, der die Remote-Instanz in einer WeakReference hält. Allein schon für's Exception-Handling ist
es sinnvoll Proxies einzusetzen, statt im Client mit RemoteExceptions zu hantieren. Die Implementierung hinter
einem Proxy, dann mit Factories abdecken, dann ist die Implementierung austauschbar (für Tests ohne Server interessant).

Gruß,
semi
 
G

Guest

Gast
Arghh, quatsch. Vergiss das mit den WeakReferences in Proxies. Das Ding räumt sich sehr schnell selbst auf.

Gruß,
semi
 
G

Guest

Gast
Übrigens, der einzige sinnvolle Einsatz von WeakReferences, den ich jemals implementiert habe, war eine Art
MessageBus zwischen verschiedenen Komponenten einer Anwendung. Jede Komponente hat sich da drin
registriert und die Nachrichten benannt, an denen sie interessiert ist. Entfernt man eine solche Komponente,
verschwindet sie aus dem MessageBus automatisch, da nur noch eine WeakReference existiert.
Das ganze liesse sich aber auch so lösen, dass beim Entfernen der Komponente diese aus dem MessageBus
abgemeldet wird. Wie auch immer... es gab im Team Leute, die das immer wieder vergessen haben, und
einen Haufen nicht mehr verwendeter, unsichtbarer Komponenten produzierten, die nie vom GC aufgeräumt
wurden (wegen fester Referenzen im MessageBus). Irgendwann mal hat es dann geknallt, da der Speicher
voll war. ;)

Gruß,
semi
 
T

tuxedo

Gast
So wie ich das sehe, ist mein Vorhaben weder mit WeakReferences, noch mit PhantomReferences ohne weiteres lösbar?!

Denke ich werde den Automatismus vorerst über Bord werfen. Werde es jetzt so machen, dass bei jedem erzeugen einer Instanz von Klasse A, ein Zähler inkrementiert wird. Ergänzend gibts dann eine "release()" Methode mit der man der Lib sagen kann, dass die jeweilige Klasse A nicht mehr weiter benötigt wird. Dadurch dekrementiert sich der Zähler. Ist er bei 0 angelangt werden die Netzwerkverbindungen gekappt und die Threads beendet.

- Alex
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben