[concurrency-interest] lazy finals - was: Here's why Atomic*FieldReference access checking is broken

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Thu Oct 9 06:23:56 EDT 2014


Peter,

>> [1] http://cr.openjdk.java.net/~jrose/draft/lazy-final.html
>
> That's great. I can see that there are two points encapsulated in this
> lazy finals proposal. One is the lazy assignment that can occur any time
> after constructor, restricted perhaps only to code of the declaring
> class, and the other is that such fields are *really* final, or in other
> words @Stable, meaning they can not be assigned twice, not even with
> reflection, which enables compiler optimizations. It's a little odd that
> in order to achieve *really* final behaviour and consequently better
> optimization, you would have to give up on  the definitive assignment
> rules help from javac.
I don't see how it improves the situation, except allowing lazy 
initialization. It suffers from the very same problems as final fields, 
if you want to perform multiple updates. And the price for lazy 
initialization is default value, which can't be optimized anymore.

> But what about this idea:
>
> Reflection supports updating ordinary final instance fields (via
> privileged setAccessible(true)) in order to achieve just what the lazy
> final fields are trying to achieve - lazy initialization outside
> constructor. Mainly to support Java  and other kinds of
> deserializations. I would say that any other uses of setAccessible(true)
> which assigns final field more than once are rare or non-existent. So
> why not making ordinary instance final fields *really* final by treating
> them in reflection as lazy final fields with a little tweak - the
> assignment of null/zero value to an "unassigned" field would not throw
> exception, but just be a NOOP - leave the field in "unassinged" state.
>
> This way deserialization of ordinary final fields would still work, but
> VM compiler could treat them all as @Stable, immediately optimizing huge
> codebases on a different level.
>
> Am I not seeing something in that simplified picture?
It's all about JIT compiler. Lazy finals/@Stable aren't a full match for 
final field case, but they are close.

The problem with treating final fields as lazy finals, is it can't be 
limited only to accesses through Reflection API. The change should be 
pervasive and default values should be treated specially everywhere, 
forbidding constant-folding of loads from final fields w/ default 
values. Do we really want that?

Regarding constant folding of loads from final fields, Hotspot already 
optimizes loads for static final fields and there's an experimental flag 
TrustFinalNonStaticFields for final instance fields case.

What HotSpot misses right now (to preserve correctness w.r.t. Reflection 
API) is a way to track dependencies between final fields and nmethods 
which embed their values. It would allow to invalidate all nmethods 
which rely on stale value and ensure the updated value is "visible" 
everywhere in the running application.

Best regards,
Vladimir Ivanov
>
> Regards, Peter
>
>>
>>>
>>> Now let me try to get something similar from
>>> AtomicReferenceFieldUpdater...
>>>
>>> Regards, Peter
>>>
>>>
>>>
>>> _______________________________________________
>>> Concurrency-interest mailing list
>>> Concurrency-interest at cs.oswego.edu
>>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>


More information about the Concurrency-interest mailing list