[concurrency-interest] DirectByteBuffers and reachabilityFence

Vitaly Davidovich vitalyd at gmail.com
Fri Dec 11 16:51:17 EST 2015


>
> So why is the DBB.get() method safe and not a potentially asynchronous
> destructor? Simply because as the last thing it does is a “return this;”
> there is no place inside it where a reachabilityFence(this) could be placed
> such that the receiver would not be used afterwards! This doesn’t by itself
> mean that every call to it is done in a safe manner but it does mean that a
> reachability fence can’t fix the implementation of DBB.get() because
> DBB.get() isn’t broken.


It's been shown a few times already in this thread why DBB.get() is
actually broken, but happens to be lucky (presumably).

I think this is still safe, though, as everything until here has been
> limited to a single thread, therefore correctly synchronized, therefore
> data-race free and therefore sequentially consistent. If a single-threaded
> program could observe a crash here then it would mean the GC had observed
> the return of a method call before the method call returned, which would
> mean the thread’s execution wasn’t sequentially consistent, which is a
> contradiction. Therefore such a reordering is not a legal reordering.
>

There's no contradiction, really.  The GC does not "observe return of a
method", the GC observes oopmaps the compiler gives it; these oopmaps
describe which oops are live at the point of GC (safepoint).  If compiler
determines that `this` is not live anymore, GC will pick up on that.  The
problem is simply that JIT thinks it's dealing with plain "long" values,
but in reality that's a native pointer.  This is just an impedance mismatch
between managed and native memory playing together.



On Fri, Dec 11, 2015 at 3:56 PM, Timo Kinnunen <timo.kinnunen at gmail.com>
wrote:

> Hi,
>
>
>
> I think I’ve figured out why the implementation of
> DirectByteBuffer.get(byte[], int, int) is safe.
>
>
>
> First, please convince yourself that reachabilityFence(this) is
> semantically equivalent or at least as-if compatible with a
> reachabilityPotentiallyEnds(this) call, with the method
> reachabilityPotentiallyEnds() being where all the finalization magic is
> implemented. (This is just for illustration and not the main point.)
>
>
>
> Convinced already? Good ��
>
>
>
> First, consider a constructor. The execution of a constructor starts in a
> static context, where pretty much nothing except evaluating arguments and
> calling another constructor of the same class or some superclass
> constructor is allowed. After that call completes normally, the context
> becomes that of the newly constructed instance, all restrictions of the
> static context are lifted and the rest of the constructor proceeds to
> execute as usual.
>
>
>
> Now consider an instance method where the receiver is not used beyond a
> certain point, its bytecode with slot 0 not read after that point, and the
> native code version which therefore can overwrite and reuse the register
> housing the this-pointer as needed. Such a method could be refactored into
> methods A and B, where method A executes before B and where the receiver is
> used in A but not in B, so that method B can be static. For such a method
> an implicit reachabilityPotentiallyEnds(this) call could be considered to
> exist between the parts A and B. If the receiver does become unreachable in
> such a method then the result of such an execution would be a dual or the
> inverse to a constructor call. Let’s call such methods potentially
> asynchronous destructors:
>
>
>
> A Potentially Asynchronous Destructor is an instance method where it’s
> possible to place a reachabilityFence(this) marker in such a way that the
> receiver is not referenced after execution reaches the marker and the rest
> of the execution happens in an effectively static context.
>
>
>
> Given this definition, any method where an explicit
> reachabilityFence(this) needs to be inserted so that the boundary between A
> and B moves to some later position to guarantee its safety is a potentially
> asynchronous destructor.
>
>
>
> So why is the DBB.get() method safe and not a potentially asynchronous
> destructor? Simply because as the last thing it does is a “return this;”
> there is no place inside it where a reachabilityFence(this) could be placed
> such that the receiver would not be used afterwards! This doesn’t by itself
> mean that every call to it is done in a safe manner but it does mean that a
> reachability fence can’t fix the implementation of DBB.get() because
> DBB.get() isn’t broken.
>
>
>
> I think this is still safe, though, as everything until here has been
> limited to a single thread, therefore correctly synchronized, therefore
> data-race free and therefore sequentially consistent. If a single-threaded
> program could observe a crash here then it would mean the GC had observed
> the return of a method call before the method call returned, which would
> mean the thread’s execution wasn’t sequentially consistent, which is a
> contradiction. Therefore such a reordering is not a legal reordering.
>
> So, what do you think? Sound reasoning or not?
>
>
>
>
> --
> Have a nice day,
> Timo
>
> Sent from Mail for Windows 10
>
>
>
>
>
>
> *From: *Gil Tene
> *Sent: *Friday, December 11, 2015 06:01
> *To: *Peter
> *Cc: *Doug Lea;concurrency-interest at cs.oswego.edu
>
> *Subject: *Re: [concurrency-interest] DirectByteBuffers and
> reachabilityFence
>
>
>
>
>
>
>
> > On Dec 10, 2015, at 6:47 PM, Peter <jini at zeus.net.au> wrote:
>
> >
>
> > Would another workaround be to use a phantom reference  for the DBB?
>
>
>
> That's exactly what sun.misc.Cleaner already does, and DBB already uses a
> cleaner. Cleaners and phantom references (or weak, or soft, or finalizers)
> do not get rid of the race. A DBB 'this' can become unreachable between
> computing an address and accessing it, GC picks up on that and enqueues the
> phantom reference (the Cleaner object), and the Cleaner object explicitly
> frees the buffer memory that was held by the DBB instance. Even though the
> DBB memory isn't reclaimed until the next GC, that doesn't matter, since
> the buffer has been freed [and potentially recycled elsewhere] before the
> unsafe call to perform the last read or write operation into it is made.
>
>
>
> There is currently (prior to reachabilityFence) no way I know of in Java
> to close this race in DBB short of following each unsafe access (e.g. in
> each put or get) with some carefully crafted (and also expensive and/or
> optimization-hurting) volatile accesses. E.g. you can add an operation that
> stores 'this' to an extra volatile field initialized to point refer to
> 'this'. E.g. I think something like: ... unsafe(…); this.dummy.dummy =
> this; … might be sufficient to ensure that 'this' is reachable until after
> the unsafe call if dummy is volatile. But it will make buffer operations
> dead slow...
>
>
>
> >
>
> > The memory isn't reclaimed by gc until the phantom reference is cleared
> or becomes reachable.
>
> >
>
> > The phantom reference queue functionality could be implemented in static
> methods and fields.  Classes aren't gc'd until all classes in a ClassLoader
> and the ClassLoader itself becomes reachable.
>
> >
>
> > Just curious.
>
> >
>
> > Regards,
>
> >
>
> > Peter.
>
> >
>
> > Sent from my Samsung device.
>
> > ---- Original message ----
>
> > From: Doug Lea <dl at cs.oswego.edu>
>
> > Sent: 11/12/2015 10:14:54 am
>
> > To: concurrency-interest at cs.oswego.edu
>
> > Subject: Re: [concurrency-interest] DirectByteBuffers and
> reachabilityFence
>
> >
>
> > On 12/10/2015 07:56 AM, Andrew Haley wrote:
>
> > > On 12/10/2015 12:51 PM, Vitaly Davidovich wrote:
>
> > >> I can see a few reasons against extending `this` lifetime at this
> stage of
>
> > >> java's life, but what were the objections last time(s) this came up?
>
> > >
>
> > > Basically twofold.  Mostly efficiency, but also a reluctance to change
>
> > > long-settled language semantics.  Making changes to something as
>
> > > fundamental as this is always much tricker than people expect.  The
>
> > > great advantage of reachabilityFence is that we can do it without a
>
> > > lot of complex argument and politics.
>
> > >
>
> >
>
> > Like Andrew and others who have seen periodic protracted
>
> > discussions of this issue over the past decade or so, I'm not
>
> > too optimistic.
>
> >
>
> > But this is also one reason for considering a @Finalized annotation
>
> > for fields (not classes!), that would give essentially this
>
> > guarantee only in those cases it was requested. Compilers would
>
> > translate methods/blocks accessing @Finalized field r
>
> > (as in .. use(r); ...)  to  the equivalent of:
>
> >    try { ... use(r); ... } finally { reachabilityFence(); }
>
> >
>
> > In the mean time, users can at least arrange this manually though.
>
> > There is no reason to believe that the performance impact would
>
> > be any different in manual vs automated forms, as long as some of
>
> > us are willing to help hotspot minimize it.
>
> >
>
> > -Doug
>
> >
>
> >
>
> > _______________________________________________
>
> > Concurrency-interest mailing list
>
> > Concurrency-interest at cs.oswego.edu
>
> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
> >
>
> > _______________________________________________
>
> > Concurrency-interest mailing list
>
> > Concurrency-interest at cs.oswego.edu
>
> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
>
>
>
>
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20151211/b2b362b4/attachment-0001.html>


More information about the Concurrency-interest mailing list