lazy statics design notes

John Rose john.r.rose at
Fri Mar 1 00:11:05 UTC 2019

On Feb 28, 2019, at 7:54 AM, Brian Goetz <brian.goetz at> wrote:
>> I think that trying to come that will encompass lazy instance field and lazy static field is a trap, because in the lazy instance case there is no constant pool to store the value.
> I tend to agree with Remi on this one.  Condy may be a “mere” implementation tactic, but it’s a darn good one, it has the semantics we want, and the use case of lazy statics is far more important than lazy instance vars.  (We we would be happy if we only had lazy statics and not lazy instances.) 

See previous message.  I agree with what you are saying, with one reservation,
that "far more important" is a time-dependent assertion; it can change.

There was a time when inner classes were "far more important" than lambdas.
Internally in the JDK we make *heavy use* of lazy non-statics, in the form
of @Stable fields.  This genie is going to come out of its bottle sooner or

And, while agreeing with you (with that one reservation), I still say it's smart
to exclude the T.default value for a lazy value.  If we don't do that, we *block*
ourselves from removing "static" as a constraint.  Or we put off the irregularity,
because we will have to say "lazy statics can have T.default but lazy non-statics

In a nutshell:  We should make *both* moves, exclude T.default *and* align
with condy.

The limitation against T.default can be spun, to many users, as a common sense
error check, against uninitialized variables.  To more curious users, it can be spun
as a conscious reservation for efficient implementations.

Scala went the other way with their lazies and they have struggled (in vain I
think) with the consequences.  You need transactional memory to do race-free
initialization of 64-bit lazies, if you don't reserve a neutral value.  Let's learn
from their difficulty.

We have enough foresight here to accept the irregularity now, when it will do
the least damage.

> Note too that the DynamicConstantValue story is a tradeoff to enable a binary compatible migration from non-lazy to lazy; I think this is a sort of corner case, as the vast majority of field accesses are within the same class.  If we didn’t care about binary-compatible migrations for public static final fields, there’s a translation-based story that is way simpler — cross-class field access desguars to invocations of a synthetic accessor.  

Desugaring a field to a method is a simple move, but it's not a free move.
Iit has the usual problems of virtualizing something the user thinks is
concrete.   I think it's at least as disruptive than making a limitation on
the value space of lazies.

Also, this assertion is certainly time-dependent:

> the vast majority of field accesses are within the same class

That's true because the existing options for exporting fields
as API points are so limited.  Adding features like lazy finals
or sealed (semi-public) fields will increase the applicable
use cases.  If and when it becomes safer to expose a field
outside the capsule, more folks will build fields into their

— John

More information about the valhalla-spec-observers mailing list