views:

416

answers:

7

Is there a way to create register a handler that will be called exactly at the time when the last reference to a certain object is released?

An example would be an object that is backed by a physical data file and once the object become unreferenced, the file should be closed and than renamed. It would be nice if this was possible without having to explicitly call a "close" method on that object.

All the notification mechanisms I am aware of from the Weak/Phantom reference area only state that notification will occur at some point in time but there is no gurantee as to when this will happen...

+12  A: 

In short, no.

The Java specification explicitly denies you the ability to know when the last reference is released. JVM implementations (and optimizations) depend on this. There is no hook.

Jason Cohen
+4  A: 

From my understanding, and I've looked for some time to find a "destructor" for java objects, there is no way to know when you lose the last reference. Java tracks references to objects but for performance reasons, updates this information only during garbage collection.

The closest thing is the finalize method which should be called during garbage collection but there's no guarantee that it will be called even then.

dl__
+1  A: 

Problem is, "How do you implement this, without something holding a reference to the object?"

Even if you could get passed that problem, say with a service we'll call the HandleManager, the HandleManager would then have to create a new reference to the object, to pass to your handler. Then, your handler could either (a) store a reference to it, which would confuse the HandleManager which was expecting to destroy the unreferenced object; or (b) release the reference, which means that the final reference was once again released, which means the Handler has to be called again....

James Curran
A: 

You could override finalize() in your object, but that is problematic for reasons others have mentioned.

For your specific example, you could take a look at using something like File.deleteOnExit(), which would remove the file once the VM exits.

matt b
A: 

This cannot be done with Java -- it needs a reference-counting garbage collector as far as I can tell. Have you considered opening and closing your object's physical data file as needed, rather than keeping it open for the lifetime of the object?

Steven Huwig
What you describe is a possible workaround. It would have been nice if there was a way to implement such cleanups in a way that gets called once it's needed. However, this requires clients of the object to remember to explictly clean up. A possibel source for error.
VoidPointer
+2  A: 

If you need to manage external resources like files, the best you can do in java is a close() function (whatever name you choose). You can use finalize() as a "belt and suspenders" insurance policy, but that has unpredictable timing. So your main line of defense needs to be the close() function.

See my answer http://stackoverflow.com/questions/158174/why-would-you-ever-implement-finalize#158216

John M
+1  A: 

I think WeakReference does what you want. A WeakReference gets put into the ReferenceQueue as soon as its weakly reachable (i.e. all strong references are gone).

See this article by Ethan Nicholas.

If you are worried about some references not reaching the ReferenceQueue at shutdown, then keep a list of all objects created (using WeakReferences or PhantomReferences). Add a shutdown hook that checks the list for any outstanding references and perform whatever action you need.

James Schek