[jmm-dev] Non-core-model issues status

Hans Boehm boehm at acm.org
Wed Sep 17 21:45:05 UTC 2014


On Tue, Sep 9, 2014 at 4:26 AM, Doug Lea <dl at cs.oswego.edu> wrote:
>
> On 09/07/2014 01:55 AM, Hans Boehm wrote:
>>
>> we seem to have lots of evidence that essentially everyone currently gets
>> this code wrong, introducing premature deallocations.
>
>
> Continuing in vacillation mode.... What do you think of
> the following concrete version of Jeremy's original
> suggestion:
>
> 1. Introduce reachabilityFence (or whatever name;
> How about "keepReachable"?)
>
> 2. Spec at syntax level that every declaration and
> use of a local (or param) ref to an object of a class F
> defining finalize() is translated from:
>   F f;
>   ...
>   <end of scope>
> to:
>   F f;
>   try {
>     ...
>     <end of scope>
>   } finally
>      if (f != null) reachabilityFence(f);
>   }
>
> It might be a little challenging to spec this to cover multiple
> refs while keeping blocked scopes, but it seems feasible.

I think that's similar to the earlier proposal with annotations, except
that we're back to "defining finalize()" as the criterion for when to apply
it.  I think that's the wrong criterion.  Counterexamples:

- Any class that uses a finalizer guardian (recommended practice in places,
I think) to perform finalization on its behalf.

- Any object that's "finalized" by enqueuing it on a reference queue
instead of using a "finalize()" method.  (Recommended practice to deal with
the lack of finalize() ordering.)

I think we need a field annotation A that basically says: "This field
becomes unusable once the enclosing object becomes unreachable".  That's
only loosely correlated with defining a finalize() method.  We then
essentially guarantee that every method that uses a field x.f, where f is
annotated with A keeps x reachable as long as that would be expected by the
naive semantics, by performing the transformation you suggest.

I'm not sure, but I think we might be able to avoid dealing with transitive
reachability issues.  If field f is annotated with a, and I have

T' x = ...;
{
   T y = x.a;
   {
       foo(y.f);
   }
}

where x is finalizable with a finalizer that invalidates f, I should
annotate both a and f, and the right things should happen.  And that
actually makes sense, I think.

For things like new T'().a.foo(), where foo uses f, to work correctly, we
probably need something like the C++ rule in the "naive semantics", that
references stay around until the end of the enclosing full expression.

This requires more thought, but this annotation seems to be significantly
easier and cleaner to use than reachabilityFence.

Hans

>
> This seems to completely address premature finalization,
> at the expense of lack of control in the other direction.
>
> The only middle ground I see is the one you like least,
> of telling people to write their own try-finally blocks.
>
> -Doug
>
>
>


More information about the jmm-dev mailing list