How to detect when an object is no longer referenced - java

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...

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.

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.

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.

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....

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 Why would you ever implement finalize()?

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?

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.

Related

Effective Java Item 7: Avoid Finalizers

In this amazing book the author Josh Bloch mentions:
"Oh, and one more thing: there is a severe performance penalty for using finalizers. On my machine, the time to create and destroy a simple object is about 5.6 ns. Adding a finalizer increases the time to 2,400 ns. In other words, it is about 430 times slower to create and destroy objects with finalizers."
Is there a way we can delete and object in java?
I thought we can simply let the objects fall out of scope or reset them to null. I intend to experiment this on my machine, seems like a fun idea but I am not sure how to delete and object.
Once you make the reference variable refers to null (assuming last reference) and that variable gets out of its scope, then the object is eligible to be garbage-collected at next garbage-collection cycle.
An object will cease to exist when there are no longer any strong rooted references to it; in most cases that's exactly what should happen. In some cases, however, an object will ask an outside entity to do something on its behalf, possibly to the detriment of other entities, in exchange for a promise to let that other entity know when its services are no longer required. For example, a "File" object might ask the OS for exclusive access to a file; until the OS is told that such access is no longer required, it will block everyone else's ability to use that file.
If an object which had made such a promise were abandoned and simply ceased to exist, the outside entity would keep on doing whatever it had been asked to do, to the detriment of everyone else, even though its actions were no longer of any benefit to anyone. To avoid this situation, Java allows objects to request notification when the GC notices that they seem to have been abandoned. Such notifications will be given (i.e. Finalize will be called on such objects) before the objects cease to exist, but there's no real guarantee of timeliness beyond that. An object which is finalized can then notify any and all entities acting on its behalf that they should stop doing so.
The creators of Java may have expected finalizers to be the primary mechanism by which objects could notify outside entities that their services are no longer required, but finalization really doesn't work very well. Other mechanisms such as AutoCloseable or PhantomReference are better in many cases.

android / java - how to be notified when there is no reference to an instance

this question is for either android or java .
suppose i have an instance of a class (even a thread) .
i wish that in order to make it fool proof against forgetting to dispose/close the instance (and avoid any possible memory leaks) , if there are no more references to this instance , it will automatically call a specific method , disposing/closing itself (in case of a thread , it will probably interrupt itself) .
is it possible to enforce such a thing?
if needed , i don't mind that such a thing will occur only during GC .
if there are no more references to this instance , it will
automatically call a specific method , disposing/closing itself (in
case of a thread , it will probably interrupt itself)
finalize() does what you describe here. You very rarely see it used though, and there are some pitfalls when using it. As you cant control garbage collection, you cant be sure when finalize will be run, if ever! From the api:
the usual purpose of finalize, however, is to perform cleanup actions
before the object is irrevocably discarded. For example, the finalize
method for an object that represents an input/output connection might
perform explicit I/O transactions to break the connection before the
object is permanently discarded.
You cant enforce garbage collection. You can only suggest the JVM to do so using System.gc(), but it is not guaranteed that it will be done.
I know this is very late but I hope it might help someone someday.
You can receive such events this by using the using the library that i am developing called gcRadar. It provides events when an object is orphaned and after the actual garbage collection of the object.
Any suggestions for improvements in the library are welcome.
There is no way to access the references held by the VM. As Zavior suggested, the only way to know for sure that an object, or an "island" of objects is inaccessible, is to use the finalize method.
Please note that you will only get notified during GC runs. So it does not really help closing/disposing resources that are still referenced but should be closed. If you want to do that as well and do not want to use such constructs as try/catch/finally, you should write a manager class for the resources.
With any of the possibillities, including a manager class, you will not get a "bulletproof" way to consolidate your resources. Being careful is the best solution IMHO.
EDIT:
I have found this thread that may be useful.

Monitor Java object destruction

I have some objects that are created/destroyed very often and that can exist in many lists at the same time. To ensure I have no references left to them the objects have a flag isDestroyed, and if this is set, each list is responsible for removing the object from the list.
However this is ofcourse a growing ground for memory leaks. What if I forget to remove objects from one of the lists? To visually monitor that the program behaves correctly, I override finalize and increase a global variable to track destructions (not a formal test, only to get an idea). However as I have no control over the GC, I could in theory wait forever until something is destroyed.
So the question is two-fold: When having objects that are in multiple lists, is a "isDestroyed" considered a good way to control the object lifetime? It forces everyone who uses the object to take care to remove it from their lists, which seems bad.
And, is there any good way to see when the reference count reaches zero on an object, ie when its scheduled for destruction?
EDIT: To be more specific, in my case I my objects represent physical entities in a room. And I have one manager class that draws each object, therefore it is in one list. Another list contains all the objects that are clickable, so there I have another list. Having all objects in one list and using polymorphism or instance of is not an option in this case. When a object is "destroyed", it should neither be shown or clickable in any way, therefore I want to remove it from both lists.
You should have a look at the java.lang.ref Package.
And, is there any good way to see when the reference count reaches
zero on an object, ie when its scheduled for destruction?
You can use the ReferenceQueue Object
From JavaDoc of java.lang.ref.ReferenceQueue
Reference queues, to which registered reference objects are appended
by the garbage collector after the appropriate reachability changes
are detected.
I think this what WeakReference and ReferenceQueue is for - you create a WeakReference for the object you are tracking and associate it with a ReferenceQueue. Then you have another thread that processes WeakReference(s) as it is returned from ReferenceQueue.remove(). WeakReference's are added to ReferenceQueue when the referenced objects is GC'd. But can you give an example on what these lists you are trying to clean up when the referenced objects are dead?
The way this is usually handled is through the Observer pattern. Each list attaches a destroy-listener that gets notified upon destruction. How this meshes with you architecture, I have no details to judge from.
If you want to be notified I'm almost sure you need PhantomReference, read here:
http://weblogs.java.net/blog/2006/05/04/understanding-weak-references

Is it possible to make GC manage native object's lifetime?

With C++ and C# experience and some little Java knowledge I'm now starting a Java+JNI (C++) project (Android, if that matters).
I have a native method, that creates some C++ class and returns a pointer to it as a Java long value (say, handle). And then other native methods called from Java code here and there, use the handle as a parameter to do some native operations on this class. C++ side does not own the object, it's Java side who does. But in the current architecture design it's hard to define who exactly owns the object and when to delete it. So it would probably be nice to make Java VM garbage collector to manage the object's lifetime somehow. The C++ class does not consume any resources, except some piece of memory, not large. So it's OK, if several such objects will not be destructed.
In C# I would probably wrap the native IntPtr handle in some managed wrapper class. And override it's finalizer to call native object's destructor when the managed wrapper is garbage collected. SafeHandle, AddMemoryPressure, etc. might be also of help here.
This is a different story with Java's finalize. The second thing you know after 'Hello world' in Java, is that using finalize is bad. Are there any other ways to accomplish this in Java? Maybe using PhantomReference?
Well let's consider the reason WHY finalize and Co are problematic: As you know there's no guarantee that the finalize will be called before the VM is shut down, which means that special cleanup code won't necessarily run (imo a bad decision, I don't see any problems to run through the finalize queue at cleanup, but well that's how it is). Also this is exactly the same situation in C#
Now your objects only consume memory, which will be cleaned up by the OS anyhow when the VM is destroyed, so the only case where finalize is problematic won't matter for you. So yes you can indeed use this variant and it'll work perfectly fine, but it may not exactly be considered a great architectural design - and as soon as you add resources to your C++ code where the OS doesn't handle the cleanup correctly you will run into problems
Also note that implementing a finalizer results in some additional overhead for the GC and means it takes two cycles to cleanup one of these objects (and whatever you do, don't ever save an object in the finalize method)
If you understand why you should avoid using Java's finalize method, you will also understand how to use it correctly. Using finalize for closing system resources (files and handles) is bad because you don't actually know when those resources will be closed and released. Using complex finalize logic is bad as your object reference can leak out and get pinned in memory again.
For your scenario, it is perfectly fine to use finalize.
using a wrapper with a finalizer is a decent solution here
but if you really don't wanna do that you can use a PhantomReference with a ReferenceQueue to clean it up (but you are going to require a separate thread to poll the queue)
So how can we achieve it using phantom reference.
Create a wrapper object for your native intPtr object. Create a
phantom reference(with a reference queue) on the wrapper object.
Create and maintain a map of phantom reference to intPtr.
Create a thread that will be monitoring the reference queue for finalized
wrapper object instances.
This thread will get the phantom reference from reference queue, lookup intPtr using phantom reference and call destructor on native int object referenced by intPtr.
While all this happening, you can go about happily using the
wrapper object in your java code.

I'm pretty sure finalize is still bad news on later JVMs--is there an alternative?

I would like to implement a ORM-style system that can save updates to POJOs when they are no longer reachable by the caller.
I thought the reference classes could do it, but they seem to only enqueue the reference after the object has been cleared (I was hoping it was when they were able to be collected), so once enqueued the .get() method will always return null.
I could use a finalizer but last time I checked those were questionable (Not guaranteed to run promptly or run at all)--I believe a combination of finalizers and runShutdownHook() would work but that's getting into fairly swampy territory.
Is there another path I'm not thinking besides the obligatory "Just have the caller call .save() when he's done"?
Are you just trying to avoid having to call save() on every POJO that you modify?
This can be done reliably using a persistence session object, like this:
Open a new session object.
Load objects via the session object. The session object maintains references to all the objects it loads.
Make any changes to the loaded objects. It is not necessary to call a save method on updated objects.
Close the session object. The session saves all of its objects. It might even be fancy enough to keep a copy of clean loaded data, compare all of its objects to the clean data, and save only the ones that have been modified.
And if you don't want to pass session objects through your code, you can take things a step further with the Unit of Work pattern, associating a session object to the current thread:
Start a unit of work. This creates a session object behind the scenes and associates it with the current thread.
Load objects. Whenever an object is loaded, your ORM automatically associates it with a session object based on the current thread.
Make any changes to the loaded objects. It is not necessary to call a save method on updated objects.
Complete the unit of work. This closes the session object, saving all the objects.
This fixes several problems with a reachability based solution:
You are not relying on nondeterministic garbage collections, which may have a long time between runs, or not run at all.
All objects modified in one operation are saved together. If you rely on reachability, different objects modified in the same operation can become unreachable at different times, meaning your modifications can be saved to the database in bits-and-pieces.
Rollback is much easier - just give your session object a rollback() method. With a reachability solution, you would need to remember to call rollback() on every modified POJO if an operation fails, which is really the same as your original problem.
Perhaps see http://nhibernate.info/doc/patternsandpractices/nhibernate-and-the-unit-of-work-pattern.html or research the Unit of Work pattern and emulate some of those ideas.
Use the Observer Pattern do build a ClearanceManager and some Destroyables.
IDestroyable is an interface, which is used for the observers it contains the method public void destroy()
The ClearanceManager is the Subject of the Observerpattern. Maybe use Singleton here to ensure you have just one ClearanceManager object in your application.
Use a Set internaly inside the ClearanceManager (not a List to ensure Objects can just be added once)
support an addDestroyable(IDestroyable destoryable) method (and maybe a removeDestroyable one).
During Runtime the Classes for which you need some destructor emulation, can register them self at the ClearenceManager. ClearenceManager.getInstance().addDestroyable(this);
The ClearanceManager has an doClearance() method, which should just be called at the end of the Main method. It iterates threw the private Set and calls destroy() on every IDestroyable object.
Doing it this way you can emulate destructors, without using them, because using destructors you are losing control about the existance of myabe needed object.
You do not know when overwriting finalize, when it is called.
Maybe, if you do not want to call doClearance() in your Main method you can use here, but just here, a real destructor finalize(). Because there are references in the ClearenceManager to the needed Objects, they will not be destroyed first. But maybe mhh, if there are cross references .... better do not use finalize, use doClearance() and have fun with it :)
I think you are barking up the wrong tree here.
All of Java's finalizer and Reference mechanisms based on reachability depend on the garbage collector to determine whether the respective objects are reachable. So if you use any of the Reference mechanisms for some kind of finalization, you run into much the same issues that make finalize a bad idea.
It is technically possible to implement your own mechanisms for doing reachability; e.g. by implementing your own application-specific reference counting. However, it is likely to be expensive, fragile, and make your code look horrible. (Reference counting in Java is likely to be messier and more fragile than in C++, because you can't overload reference assignment operators to ensure that reference counts are adjusted transparently. So every reference assignment needs to be wrapped in a method call.) So I'd say that doing your own reachability analysis is a bad idea.
So, to be practical you need to either:
rethink your design so that you don't do things based on reachability, or
live with the consequences of using finalize.
The first option is clearly the best, IMO.
maybe you can subclass PhantomReference, and store necessary data in it for final actions.

Categories