non-volatile writes and reachability

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

non-volatile writes and reachability

JSR166 Concurrency mailing list
Hi all,

I have a question on how the JMM rules interact with GC rules around reachability.  Imagine I have object A which has a non-volatile field which is the only reference into some heavy weight object B.  I safely publish A to other threads such that at least two threads reference the A. If subsequently one of the threads nulls out that non-volatile field referencing B, would B still be considered reachable, and thus not eligible for GC?  I imagine the answer is yes in theory, but either no or unlikely in practice?

My apologies if this has been previously asked and answered, I couldn't find it in the archives.

thanks,

Mark

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest
Reply | Threaded
Open this post in threaded view
|

Re: non-volatile writes and reachability

JSR166 Concurrency mailing list
On 2/13/19 7:56 PM, Mark Falco via Concurrency-interest wrote:
> I have a question on how the JMM rules interact with GC rules around reachability.  Imagine I have
> object A which has a non-volatile field which is the only reference into some heavy weight object
> B.  I safely publish A to other threads such that at least two threads reference the A. If
> subsequently one of the threads nulls out that non-volatile field referencing B, would B still be
> considered reachable, and thus not eligible for GC?

The general rule about interactions with runtime is this: whatever happens in JVM, whatever JVM
subsystems do, the behavior should be consistent with JMM rules. Neither GC, nor JIT, nor
interpreter can introduce violations.

The concrete answer depends on effect you are after. What does it mean "object not eligible for GC":
the backing storage is not reclaimed? object contents are accessible? associated finalizer is not
able to run? the relevant weak references are not enqueued? something else?

If one of the threads have read the reference to B into the local variable, it would to be able to
read its contents fine (since it was published safely), as JMM mandates. The finalizers might run on
that object, it might get queued on ReferenceQueue, etc. while the thread _appears_ to hold the
reference to it, because local variables do not necessarily extend the liveness of the object
[1][2]. The optimizers might cache the values of the object fields and still be able to "access
them", when object is "actually" gone. The object might stay untouched by runtime at all, until it
is safe to do so.

So, JVM would not crash, JMM rules would hold, but the object might be in this heisen-state where it
appears both reachable and unreachable at the same time, depending on definitions :)

-Aleksey

[1] https://shipilev.net/jvm-anatomy-park/8-local-var-reachability/
[2] http://www.hboehm.info/popl03/slides.pdf


_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: non-volatile writes and reachability

JSR166 Concurrency mailing list
In reply to this post by JSR166 Concurrency mailing list
It is certainly possible to build something that would keep an object indefinitely reachable even after all references to it (in the heap and in programmatically declared local variables) have been nulled. See below. But in most practical situations a subsequent ordering operation will take care of reachability, as most java GCs leverage precise information about the location of references (in the heap and on the stack) to only consider actually-reachable-from-roots things reachable.

Class b {
        int x;
}

class A {
        boolean done = false;
        B b;
        A(B b) { this.b = b; }
}


static final A a = new A(new B());

Thread 1:
done = true;
a.b = null;


Thread 2:
...
while (!a.done) {
        if (a.b != null)
                total += a.b.x;
}

Thread 2 can remain in an infinitive loop,. and the instance originally referred to by a.b can remain reachable forever, because it can be validly transformed to the equivalent of:

boolean localDone = a.done;
B localB = a.b;
if (localB != null) {
        while (!localDone) {
                total += localB.x;
        }
} else {
        while (!localDone) {
        }
}




> On Feb 13, 2019, at 10:56 AM, Mark Falco via Concurrency-interest <[hidden email]> wrote:
>
> Hi all,
>
> I have a question on how the JMM rules interact with GC rules around reachability.  Imagine I have object A which has a non-volatile field which is the only reference into some heavy weight object B.  I safely publish A to other threads such that at least two threads reference the A. If subsequently one of the threads nulls out that non-volatile field referencing B, would B still be considered reachable, and thus not eligible for GC?  I imagine the answer is yes in theory, but either no or unlikely in practice?
>
> My apologies if this has been previously asked and answered, I couldn't find it in the archives.
>
> thanks,
>
> Mark
> _______________________________________________
> Concurrency-interest mailing list
> [hidden email]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest

_______________________________________________
Concurrency-interest mailing list
[hidden email]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

signature.asc (849 bytes) Download Attachment