DAS SOLLTE MIT JAVA 9 OBSOLET SEIN!
Verwenden Sie java.util.Cleaner
stattdessen! (Oder sun.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:
class Foo implements Cleanup {
//...
public Foo() {
//...
this.registerCleanup((value) -> {
try {
// 'value' is 'this.resource'
value.close();
} catch (Exception e) {
logger.warning("closing resource failed", e);
}
}, this.resource);
}
Und dann gibt es die noch einfachere Methode zum automatischen Schließen, die ungefähr das Gleiche wie oben tut:
this.registerAutoClose(this.resource);
So beantworten Sie Ihre Fragen:
[was nützt es dann]
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.
Aber wozu dient dieses Konzept / diese Klasse?
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.
Haben Sie dies jemals in einem Ihrer Projekte verwendet oder haben Sie ein Beispiel, wo wir dies verwenden sollten? Oder ist dieses Konzept nur aus Interviewgründen gemacht;)
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.