I am reading about the GC and read that when an object becomes eligible for garbage collection, the GC has to run the finalize
method on it. The finalize
method is guaranteed to run only once, thus the GC marks the object as finalized and gives it a rest until the next cycle.
In the finalize method, you can technically “resurrect” an object, for example, by assigning it to a static field. The object would become alive again and not eligible for garbage collection, so the GC would not collect it during the next cycle.
The object, however, would be marked as finalized, so when it would become eligible again, the finalize method would not be called. In essence, you can turn this “resurrection” trick only once for the lifetime of the object.
I find this fascinating. However, if my variable is non-static, how to I change it to the static inside the finalize
method?
Remember:
An object becomes eligible for Garbage collection or GC if it is not reachable from any live threads or by any static references. So the hack is to add the object to a static resource inside the finalize
method and this will prevent the garbage collection for only one time. The finalize
method is protected, so, can be overridden by subclasses, whether they are in the same package or not.
This is a dangerous practice and no need to use inside application code.
Changing a variable definition at runtime isn't easy and in some cases next to impossible. There might be some nasty reflection tricks that might involve inline compiling, classloading etc. but you shouldn't do that. Changing a variable from static to non-static or vice versa would also involve moving the data around in storage and deal with potential collisions - so don't do that.
Anyways variables are just references and to resurrect an object you'd just need to create a new reference from a live thread. That could be done with some collection that's referenced by a static variable and which the this
reference is added to.
Example (for illustration purposes only, do not use it unless you really know what you are doing and have a good reason to):
class NastyResurrector {
public static Collection<Object> RESURRECTED_OBJECTS = ...;// use whatever collection implementation you like
}
Then in finalize()
you'd call NastyResurrector.RESURRECTED_OBJECTS.add(this)
and there you have your reference.
However, I'll quote from the source of your question (question Q11):
Beware that this ugly hack should be used only if you really know what you’re doing
That's the most important takeaway in my opinion.