Das einzige was ich weiß PhantomReference
ist:
- Wenn Sie die
get()
Methode verwenden, wird immernull
das Objekt zurückgegeben und nicht das Objekt. Was nützt es? - Durch die Verwendung
PhantomReference
stellen Sie sicher, dass das Objekt nicht von derfinalize
Methode wiederbelebt werden kann.
Aber wozu dient dieses Konzept / diese Klasse?
Haben Sie dies jemals in einem Ihrer Projekte verwendet oder haben Sie ein Beispiel, wo wir dies verwenden sollten?
FakeReference
oderNonReference
.Antworten:
Ich habe
PhantomReference
s in a verwendet simplen, sehr speziellen Speicherprofiler verwendet , um die Objekterstellung und -zerstörung zu überwachen. Ich brauchte sie, um die Zerstörung im Auge zu behalten. Der Ansatz ist jedoch veraltet. (Es wurde 2004 für J2SE 1.4 geschrieben.) Professionelle Profiling-Tools sind viel leistungsfähiger und zuverlässiger, und die neueren Java 5-Funktionen wie JMX oder Agenten und JVMTI können auch dafür verwendet werden.PhantomReference
s (immer zusammen mit der Referenzwarteschlange verwendet) sind überlegen,finalize
haben einige Probleme und sollten daher vermieden werden. Hauptsächlich Objekte wieder erreichbar machen. Dies könnte mit der Finalizer-Guardian-Sprache vermieden werden (-> lesen Sie mehr in 'Effective Java'). Sie sind also auch das neue Finale .Darüber hinaus
PhantomReference
sUnd wie psd zuerst schrieb, hat Roedy Green eine gute Zusammenfassung der Referenzen .
quelle
Eine allgemeine Erklärung der Würfeltabelle aus dem Java-Glossar.
Was natürlich mit der PhantomReference-Dokumentation übereinstimmt :
Und zu guter Letzt alle wichtigen Details ( dies ist eine gute Lektüre ): Java-Referenzobjekte (oder wie ich gelernt habe, mich nicht mehr zu sorgen und OutOfMemoryError zu lieben) .
Viel Spaß beim Codieren. (Aber um die Frage zu beantworten, habe ich immer nur WeakReferences verwendet.)
quelle
Gute Erklärung für die Verwendung der Phantomreferenz:
quelle
Ich fand einen praktischen und nützlichen Anwendungsfall von
PhantomReference
denenorg.apache.commons.io.FileCleaningTracker
in commons-io - Projekt.FileCleaningTracker
löscht die physische Datei, wenn das Markierungsobjekt durch Müll gesammelt wird.Zu beachten ist die
Tracker
Klasse, die die Klasse erweitertPhantomReference
.quelle
DAS SOLLTE MIT JAVA 9 OBSOLET SEIN!
Verwenden Sie
java.util.Cleaner
stattdessen! (Odersun.misc.Cleaner
auf älteren JRE)Ursprünglicher Beitrag:
Ich habe festgestellt, dass die Verwendung von PhantomReferences fast genauso viele Fallstricke aufweist wie die Finalizer-Methoden (aber weniger Probleme, sobald Sie es richtig verstanden haben). Ich habe eine kleine Lösung (ein sehr kleines Framework zur Verwendung von PhantomReferences) für Java 8 geschrieben. Sie ermöglicht die Verwendung von Lambda-Ausdrücken als Rückrufe, die ausgeführt werden, nachdem das Objekt entfernt wurde. Sie können die Rückrufe für innere Ressourcen registrieren, die geschlossen werden sollen. Damit habe ich eine Lösung gefunden, die für mich funktioniert, da sie viel praktischer ist.
https://github.com/claudemartin/java-cleanup
Hier ist ein kleines Beispiel, um zu zeigen, wie ein Rückruf registriert wird:
Und dann gibt es die noch einfachere Methode zum automatischen Schließen, die ungefähr das Gleiche wie oben tut:
So beantworten Sie Ihre Fragen:
Sie können etwas, das nicht existiert, nicht aufräumen. Aber es könnte Ressourcen gegeben haben, die noch vorhanden sind und bereinigt werden müssen, damit sie entfernt werden können.
Es ist nicht unbedingt erforderlich, etwas anderes als das Debuggen / Protokollieren zu tun. Oder vielleicht für Statistiken. Ich sehe es eher wie einen Benachrichtigungsdienst vom GC. Sie können es auch verwenden, um aggregierte Daten zu entfernen, die nach dem Entfernen des Objekts irrelevant werden (aber es gibt wahrscheinlich bessere Lösungen dafür). Beispiele erwähnen oft, dass Datenbankverbindungen geschlossen werden müssen, aber ich sehe nicht, dass dies eine so gute Idee ist, da Sie nicht mit Transaktionen arbeiten konnten. Ein Anwendungsframework bietet dafür eine viel bessere Lösung.
Ich benutze es meistens nur zum Protokollieren. So kann ich die entfernten Elemente verfolgen und sehen, wie GC funktioniert und optimiert werden kann. Ich würde auf diese Weise keinen kritischen Code ausführen. Wenn etwas geschlossen werden muss, sollte dies in einer Try-with-Resource-Anweisung erfolgen. Und ich benutze es in Unit-Tests, um sicherzustellen, dass ich keine Speicherlecks habe. Genauso wie es Jontejj tut. Aber meine Lösung ist etwas allgemeiner.
quelle
Ich habe eine PhantomReferenz in einem Komponententest verwendet, um zu überprüfen, ob der zu testende Code keine unnötigen Verweise auf ein Objekt enthält. ( Originalcode )
Und der Test :
quelle
Es ist üblich, dort zu verwenden,
WeakReference
woPhantomReference
es angemessener ist. Dies vermeidet bestimmte Probleme, Objekte nach a wiederbeleben zu könnenWeakReference
vom Garbage Collector gelöscht / in die Warteschlange gestellt wurde. Normalerweise spielt der Unterschied keine Rolle, weil die Leute keine dummen Kerle spielen.Die Verwendung ist
PhantomReference
in der Regel etwas aufdringlicher, da Sie nicht so tun können, als ob dieget
Methode funktioniert. Sie können zum Beispiel nicht schreiben aPhantom[Identity]HashMap
.quelle
weakref.get
könnte zurückkehrennull
, und dann später ist es immer noch in der Lage, das Objekt zurückzugeben?finalize
erstellt das Objekt nicht als solches neu. Es kann das Objekt nach einerWeakReference
Rückkehrnull
von wieder stark erreichbar machenget
und in die Warteschlange stellen. / (user166390: Wie in einer Karte, die auf dem Ziel der Referenz eingegeben wurde, ebensoWeakHashMap
wie eine Identitätskarte mit Referenzen, die in Ordnung ist.)Die nützlichen Methoden zum Aufrufen (anstatt
get()
) wärenisEnqueued()
oderreferenceQueue.remove()
. Sie würden diese Methoden aufrufen, um eine Aktion auszuführen, die in der letzten Runde der Speicherbereinigung des Objekts ausgeführt werden muss.Das erste Mal wird die
finalize()
Methode des Objekts aufgerufen, sodass Sie dort auch schließende Hooks platzieren können. Wie andere bereits festgestellt haben, gibt es wahrscheinlich sicherere Methoden zur Durchführung von Bereinigungen oder Maßnahmen, die vor und nach der Speicherbereinigung oder allgemeiner nach dem Ende der Lebensdauer des Objekts erforderlich sind.quelle
Ich fand eine andere praktische Verwendung
PhantomReferences
in der LeakDetector- Klasse von Jetty.Jetty verwendet die
LeakDetector
Klasse, um festzustellen, ob der Clientcode eine Ressource erfasst, diese jedoch nie freigibt, und dieLeakDetector
Klasse verwendet diePhantomReferences
zu diesem Zweck.quelle