Reachability of an object when a thread is running one of its methods

Andrew Haley aph at redhat.com
Wed Dec 5 04:44:16 PST 2012


On 12/05/2012 12:02 PM, Carlo de Wolf wrote:
> On 12/05/2012 10:59 AM, Andrew Haley wrote:
>> On 12/05/2012 09:00 AM, Carlo de Wolf wrote:
>>
>>> The example further on shows that an object reference which is on the
>>> heap can be optimized away and thus the object can be finalized too
>>> early. A reference coming off the stack is allowed to be nullified and
>>> it would not trigger finalization. Hence a reference on the stack is a
>>> strong one.
>> Carlo, you are making this very hard work.  You write things like
>>
>> "A reference coming off the stack is allowed to be nullified and
>> it would not trigger finalization." but without reference to the
>> specification.  Does it say anything in the specification to
>> support this claim?
> 
> JLS 7 12.6.1
>
> "If these optimizations are allowed for references that are stored
> on the heap, then a Java compiler can detect that the
> finalizerGuardian field is never read, null it out, collect the
> object immediately, and call the finalizer early."
> 
> In effect, the optimization is allowed for a reference stored on the 
> stack, without having the side effect of an early finalize call.
> 
> Or am I reading it wrong?

I think so.  I don't think that the above paragraph, which begins "If
these optimizations are allowed for references that are stored on the
heap" in any way restricts optimization when references are on the
stack.  It only refers to the heap, and therefore it is not
appropriate to read into it anything about references on the stack.

>>> Probably the real issue is when the stack of the previous frame is
>>> cleared, at the start of invoke(virtual) or at the end of
>>> invoke(virtual)?
>> I'm looking at the example at https://www.ibm.com/developerworks/forums/message.jspa?messageID=14915477
>>
>> Is that what you're talking about?
> 
> Yes, specifically the code I wrote at 
> https://www.ibm.com/developerworks/forums/message.jspa?messageID=14915477#14915477. 
> 
>> You say
>>
>>> 1. The current frame holds this in variable #0. While technically it
>>> is possible to set local variable #0 to null, I find that an
>>> extremely dirty action.
>>
>> But the specification explicitly allows it.
> 
> Yup, which I personally find a dirty action. :-)
> Anyway it might warrant an extra warning in spec.
>>
>> And
>>
>>> 2. The previous frame is also holding a reference to FinalizeBug (or
>>> at least should be ;-) ) in its stack.
>>
>> But the specification does not require it to do hold such a reference.
>>
> Where does it say that?

In the explanatory text, it says

"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. For example, a Java compiler or
code generator may choose to set a variable or parameter that will no
longer be used to null to cause the storage for such an object to be
potentially reclaimable sooner."

It goes on to say:

"Another example of this occurs if the values in an object's fields
are stored in registers. The program may then access the registers
instead of the object, and never access the object again."

In my opinion, this example directly applies to your case.  In work(),
"this" is dead after this.set is read -- so the warning holds, and the
finalizer may be invoked.

Note that these are just examples: they don't limit what might happen,
but merely warn about possible consequences.

I do see this:

"none of the pre-finalization reads of fields of that object may see
writes that occur after finalization of that object is initiated."

But this doesn't apply to your example: the invocation of set.clear()
from FinalizeBug.finalize() doesn't affect any of the fields of
FinalizeBug.

> Because as you can see it has serious implications for the conceptual 
> state of an object.

I agree.  The problem (if it is one) is that the definition of
reachability is in some ways counter-intuitive, and Java programmers
who rely on an intuitive understanding of it will eventually come to
grief.

> If it is by omission then either way it should explicitly stated it or 
> have an additional warning. (At least that's my opinion. :-) )

I certainly agree that this should be discussed.  Is the JLS the right
place for such things, though?

The key phrase is this:

"A reachable object is any object that can be accessed in any
potential continuing computation from any live thread."

So, the question is what constitutes an access.  Is the execution of a
method (of an object) after that method has been started an access to
that object?  I don't think it is.

Andrew.


More information about the java-se-8-spec-comments mailing list