Reference to object during finalize

2019-01-14 21:42发布

问题:

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?

回答1:

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



回答2:

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



回答3:

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



回答4:

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.



回答5:

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.