Jeremy Manson wrote:
> To David D. and Evan - You could finalize man in any of the places David
> H. mentions if useA() and useB() don't access this, and are inlined by
> the compiler. In such code, there would be no uses of man after its
> initialization.
Thanks Jeremy, I thought for a moment I had completely misunderstood this
issue once again. Though your clarification does restrict the problem to a
subset of situations to what I was thinking - ie I don't completely
understand it either.
To Dave Detlets, and Evan, the issue relates to the optimization mentioned
in JLS 12.6.1:
"A reachable object is any object that can be accessed in any potential
continuing computation from any live thread. Optimizing transformations of a
program can be designed that reduce the number of objects that are reachable
to be less than those which would naively be considered reachable."
(I resent the use of "naive" there. I don't consider it to be naive to think
that an object is reachable when it is still being used!)
The JLS is not clear on what sort of optimisations are possible. The
discussion on this list in the past seemed - from my recollection - to imply
more situations that the JLS alludes to. The motivation for my example was
the idea that the local reference to the resource manager object might be
stored in a register and not be seen during GC as referring to a live
object, hence the object could be considered unreachable and so finalizable.
Now perhaps that situation is not allowed. But it is far from clear to me
what sort of optimizations of this nature are allowed and which are not.
To Dan Bornstein: The use of reference queues does not help in this
situation. The problem is that the object is prematurely considered to be
unreachable. Once that occurs the finalizer can run if it has one, or it
could appear in a reference queue if registered with one. Hence it could be
"processed" from the reference queue prematurely, just as the finalizer
could execute prematurely.
To Hans: What you have said seems to imply that the existence of the sync
block requires the system to know that the sync block exists and act
accordingly. I don't understand this.
I find it hard to believe that the VM/JIT would actively try to perform this
optimization. My thought - which could be quite wrong - was that it arose as
a side-effect of the JIT's actions eg. a local reference is stored in a
register and so is not seen by GC and thus an object is considered
unreachable. Based on that case you need the sync block in the current
method to force the JIT to consider that before storing the local in a
register (how much time would such an analysis take? would it be worth it?).
However, Jeremy also indicated that the premature finalization could only
occur if the methods useA and useB don't refer to 'this' - yet the JIT
doesn't know this without examining the internals of those methods, which
again seems unreasonable to me.
So I'm left - as usual - with no clear understanding of exactly what kinds
of situations can lead to premature finalizer execution. And hence no clear
understanding of the validity of proposed solutions.
Cheers,
David Holmes
-------------------------------
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:01:10 EDT