[concurrency-interest] Is Reference.reachabilityFence() needed in Reference constructor?
Alex Otenko
oleksandr.otenko at gmail.com
Mon Oct 26 17:12:35 UTC 2015
Wouldn’t it be possible to add a test that will always be false?
eg
Reference(T referent, ReferenceQueue<? super T> queue) {
this.referent = referent;
// - safepoint with GC happens, 'referent' is found weakly-reachable, 'this' Reference is hooked on the pending chain
// - ReferenceHandler thread unhooks 'this' from pending chain and tries to enqueue it, but this.queue is still null
// - BANG! NPE in Referencehandler thread which terminates it!
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
if (get() != referent) { // do a get() == referent test instead for Phantom ref
System.out.println(referent + “ expected but “ + get() + “ found");
}
}
The point being that referent would need to stay alive due to Java semantics to align with get() and queue assignment.
Alex
> On 21 Oct 2015, at 10:08, Aleksey Shipilev <aleksey.shipilev at oracle.com> wrote:
>
> On 10/21/2015 06:53 PM, Andrew Haley wrote:
>> On 10/21/2015 04:44 PM, Aleksey Shipilev wrote:
>>> Of course, this does not tell another (scary) part of the story, what if
>>> the Reference itself is not discovered as strong ref by GC, e.g. when it
>>> isn't published on heap, or scalarized by compiler, etc.
>>> reachabilityFence, as currently implemented, extends the "liveness"
>>> scope of the local variable, but does not convey anything special to the
>>> GC/runtime otherwise.
>>
>> If the Reference itself is not reachable from a strong root then the
>> Reference is dead so we don't care what happens to it. But if the
>> Reference is put on a reachable ReferenceQueue, then it's fine.
>
> Yes, if runtime stripes that instance before it is exposed anywhere
> (e.g. scalarizes the weakref), or those references are dead (e.g. the
> weakref is buried somewhere deep in garbage subgraph, and purged on
> sweep), then everything goes awry.
>
> But the thing is, a WeakReference is put on ReferenceQueue by the GC
> itself. In the object graph, ReferenceQueue does not normally reference
> weakrefs back. Before enqueueing the reference GC has to first discover
> that WeakReference -- but from where? In other words, "registering" on a
> reachable RefQueue does not make weakref to be reachable.
>
> Case in point:
>
> public class WhereIsWaldo {
>
> public static void main(String... args) throws Exception {
> for (int c = 0; true; c++) {
> new WhereIsWaldo().work(c);
> }
> }
>
> final ReferenceQueue<Object> rq = new ReferenceQueue<>();
>
> void work(int id) throws Exception {
> hideWaldo(id);
> findWaldo(id);
> }
>
> WeakReference<Object> gwr;
>
> void hideWaldo(int id) {
> // Does not work, d'uh
> new WeakReference<>(new Object(), rq);
>
> // Does not work either :(
> WeakReference<Object> wr =
> new WeakReference<>(new Object(), rq);
>
> // This also does not help... once you leave the method,
> // the weakref is gone.
> Reference.reachabilityFence(wr);
>
> // This one helps, makes Waldo reachable
> // gwr = wr;
> }
>
> void findWaldo(int id) throws Exception {
> while (Thread.currentThread().isAlive()) {
> System.gc();
> Reference ref = rq.remove(1000);
> if (ref != null) {
> return;
> } else {
> System.out.println("Where's Waldo #" + id + "?");
> }
> }
> }
> }
>
>
> Thanks,
> -Aleksey
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
More information about the core-libs-dev
mailing list