What happens if you save a reference to the current object during the finalize call? For example:
class foo {
...
public void finalize() {
bar.REFERENCE = this;
}
}
Is the object garbage-collected, or not? What happens when you try to access bar.REFERENCE
later?
Because Java is a safe language and platform, the memory is not freed. Also associated
PhantomReference
s will not be enqueued upon theirReferenceQueue
s. The VM will only ever callfinalize
on an object once. There's a nice state diagram in the JVM Spec.Typically if you do use a finaliser, you should leave the declaration as
@Override protected void finalize() throws Throwable
, so as not to disturb the API. Even better use a guarded finaliser, as in Effective Java 1st Ed.This particular trick hit the headlines (of the San Jose Mercury, anyway) when a group at Princeton used it to construct a custom
ClassLoader
from untrusted code. Although the spec has been slightly tightened (theObject
constructor has to finish executing normally before the finaliser can be called - specified in J2SE 5.0, implemented in Java SE 6), this still remains a problem area. If you are designing an API, make sure sensitive classes cannot be subclasses and save yourself much grief.This kind of thing is the reason why the use of
finalize()
is generally discouraged.The object is not garbage collected. This is know as "Object resurrection".
You must be careful with that, once the finalizer is called the gc won't call it again, on some enviroments like .NET you can re-register the finalizer but i'm not sure about java
The
finalize()
method may be invoked explicitly on thefoo
instance, or it may be invoked by the garbage collector when it tries to reclaim the storage occupied by that object.If
bar
is a valid instance, it sets theREFERENCE
field to thefoo
instance. From the garbage collector's point of view, this increasesfoo
's reference count.If an exception is thrown inside the
finalize()
method (e.g. such as aNullPointerException
due tobar
beingnull
), then the finalization process simply terminates.N.B. As others have pointed out.. your example is definitely something to be avoided.
If you absolutely must resurrect objects, this JavaWorld article suggests creating a fresh instance rather than resurrecting the instance being finalized because if the instance being finalized becomes eligible for collection again it will simply be collected (the finalizer won't be run again).