Let's say that I created a class MyClass that implements Closable. So in the close() method I am going to free some very important recources. Well since it is very important recources I created some kind of safety network (as recommended in Effective Java). Here it is:
protected void finalize(){
if (/*user didn't call close() method by himself*/){
close();
}
}
First I was very happy but later I read that finalizer are not so cool and that there is such a cool tool like PhantomReference. So I decided to change my code to use PhantomReference instead of finalize() method. I created CustomPantom extends PhantomRefernce. Here it is:
public class CustomPhantom extends PhantomReference {
//Object cobj;
public CustomPhantom(Object referent, ReferenceQueue q) {
super(referent, q);
//this.cobj = referent; can't save the refference to my object in a class field,
// because it will become strongly rechable
//and PhantomReference won't be put to the reference queue
}
public void cleanup(){
//here I want to call close method from my object,
//but I don't have a reference to my object
}
}
So as I see the only way I can get a reference to my object is to use reflection and get if from the referent field which is in the Reference class. Is this the only way to call MyClass.close() from clean up method?
P.S. I haven't posted all the code here but I tested it and all works fine. ReferenceQueue is filled by PhantomReferences, and then I can get them one by one and call cleanup method. But I fail to see how to resolve the above problem without using reflection.
You can't do something like this with phantom references, and not even reflection will help. You only get the reference in the ReferenceQueue
after GC has already occurred, so there's no more object to call close()
on.
One thing you can do -- a good idea, in point of fact -- is to use the PhantomReference
to throw an error saying you should have called close()
directly and didn't. For example, you might have the referent object have a reference to your CustomPhantom
, and call a CustomPhantom.setCleanedUp(true)
method. Then in your CustomPhantom
, if you're in a ReferenceQueue
and it's not cleaned up, you can display a warning.