views:

243

answers:

5

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?

+5  A: 

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

AlbertEin
+4  A: 

This kind of thing is the reason why the use of finalize() is generally discouraged.

Michael Borgwardt
Finalize should only be used to free references to unmanaged resources. The GC will take care of all the managed references for you eventually.
Ryan Michela
No, finalize should NOT be used for that, because it runs at an arbitrary later time, or not at all. Unmanaged resources should be freed explicitly in a finally block. At best, finalize() can be an added failsafe.
Michael Borgwardt
... but even as a failsafe, it's very problematic. As it is nondeterministic, it will turn a reproducible resource leak into an intermittent resource leak, which happens less often, but is much harder to reproduce. Been there, done that :-(.
sleske
@sleske: yeah, me too...
Michael Borgwardt
+1  A: 

The finalize() method may be invoked explicitly on the foo 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 the REFERENCE field to the foo instance. From the garbage collector's point of view, this increases foo's reference count.

If an exception is thrown inside the finalize() method (e.g. such as a NullPointerException due to bar being null), then the finalization process simply terminates.

N.B. As others have pointed out.. your example is definitely something to be avoided.

octy
+2  A: 

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

Aaron Maenpaa
A: 

Because Java is a safe language and platform, the memory is not freed. Also associated PhantomReferences will not be enqueued upon their ReferenceQueues. The VM will only ever call finalize 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 (the Object 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.

Tom Hawtin - tackline