RE: JavaMemoryModel: Finalizers

From: David Holmes (
Date: Mon Apr 07 2003 - 00:56:45 EDT

Bill Pugh wrote:

> In Sun's JDK 1.4.2 rt.jar,
> there are 367 inner classes that never dereference this$0.
> We want to allow the compiler to remove these fields, because
> they can keep the outer instance alive past any possible use.

Why does the VM care? If the presence of these inner classes is
incorrect and causes excessive delays in allowing reclamation of
garbage, then bug reports will be filed. It is not the VM's job to try
and fix this.

> At any rate, there is no syntactic way to declare a static anonymous
> inner class. So either we have to change the syntax, or allow the
> compiler to remove the unused this$0 field.

How about just rewriting the code to use named static nested classes?
;-) No need for syntax changes or compiler trickery - just write the
code the way it is meant to be written.

> * We provide a new static method in class java.lang.System:
> public static void keepAlive(Object o)

> Most of the issues we've discussed would be solved by
> putting a call to
> keepAlive(this) at the end of any method that uses this.

Which seems like a really hack way of "touching" the this reference in
a way that can't be optimised away.

Such hacks should not be necessary.

> * Many/most finalizers exist only to free data structures associated
> with an object that are allocated in the C heap. To help
> eliminate
> these finalizers, we provide a new function that can be
> called from
> native code, called something like:
> void freeOnceGarbageCollected(Object ref, void * memory)
> this function has the semantics that once ref has been
> garbage collected, the C heap memory is freed

But that doesn't fix the current problem - which is that the object
may be garbage collected and the C memory freed *before* a thread has
finished using the C memory. What we need here is not a different
mechanism for freeing the memory when the object is GC'ed, but a way
to ensure that the object can't be GC'ed while the memory is still in

> * Any object is considered alive for the duration of any
> JNI call such that
> a reference to the object has been passed as an argument
> to the JNI call.

That makes sense.

> * To handle the problem mentioned by Josh, (the fact that
> finalize methods can forget to invoke super.finalize()),
> we can provide a new static method of System
> public static void runOnceGarbageCollected(Object
> ref, Runnable task)

I don't see how this fixes anything. First, if you forget to invoke
super.finalize it's a programming error and your problem. Why should
the VM be concerned? Second, if you can't use finalize correctly, why
should you be able to use the above correctly? Can't the above be
effectively done via a reference queue directly anyway?

My feeling with these "optimisations" is similar to what I've felt
about so many issues in the JMM. The optimisation (reclamation of
objects earlier than might naively be assumed) is only valid when the
affects of the optimisation are not observable to the program. If the
affects are observable - which they are when considering finalization
and reference queues - then the optimisation is not valid and so
should not be performed.

Bill later wrote:
> Maybe this is too harsh. Maybe we need a rule that liveness
> optimizations can only apply to methods variables, and that any
> object reachable via a field of a reachable object is itself
> reachable.

Which sounds like the more general form of Hans Boehm's suggestion,
that I already suggested - and which Hans thought was too general.

David Holmes

JavaMemoryModel mailing list -

This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:43 EDT