lazy statics design notes
Remi Forax
forax at univ-mlv.fr
Sat Mar 2 21:47:10 UTC 2019
Hi John,
the semantics of a lazy final instance field and a lazy final static field are different, likewise the semantics of an instance field and a static field are different too, by example the static fields are initialized under a lock but there is no implicit lock around the instance fields initializations in a constructor.
The concept of "lazy final" is coarsely the same between static and instance fields, but semantics is slightly different, people will get a NPE if they try to use null with an instance field but not if it's a static field because the constant pool does the bookkeeping.
Disallowing null for lazy static field goes a step too far in term of design, because it introduce an arbitrary limitation for the shake of having a common semantics. I think it's an overdesign.
And there are two other arguments:
- as you said, the static lazy final is very more important than the instance one and we want to help users to over use it so if we can not introduce a discrepancy between a static final and a lazy static final, we should do it.
- why null is not a valid value for a lazy final instance field ? We can decide to allow null to signal that the instance field is still not initialized despite that the initialisation sequence has been run.
Rémi
----- Mail original -----
> De: "John Rose" <john.r.rose at oracle.com>
> À: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> Cc: "valhalla-spec-experts" <valhalla-spec-experts at openjdk.java.net>
> Envoyé: Samedi 2 Mars 2019 20:37:35
> Objet: Re: lazy statics design notes
> On Mar 1, 2019, at 3:47 AM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com>
> wrote:
>>
>> From a technical perspective I don't think there's any issue. You get condy
>> semantics, which, as you say, is well defined w.r.t. cycles and laziness etc.
>>
>> From a language perspective I see an issue if we expect, as we said, that most
>> people will just jump in and replace 'static' with 'lazy-static'. That is gonna
>> have all sorts of behavioral incompatibilities.
>
> The first time someone gets an error because the value of the lazy-static is
> null,
> they will say "those idiots", etc. Whereas we want them to think of adding
> laziness
> as a simple, foolproof way to get certain kinds of performance improvements.
>
> This is a good point, and may overcome my arguments. It will push the friction
> forward in time, to the place where we add non-static lazies; at that point we
> will have a less pleasant choice between transactional memory and reserving
> the value I am asking we reserve *now*.
>
> (BTE, this is a classic example of something that looks great from the VM
> looking
> upward doesn't look so great from the user model looking downward.)
>
> So, I want to defend my proposal a little more, not only by saying we'll pay
> a cost later if we don't reserve the value now, but also by noting that your
> point about "all sorts of behavioral incompatibilities" applies more evenly
> than you may think, to both proposals (reserve a value, vs. don't reserve).
>
> Even if you allow the full range of values, including null, there will be
> all sorts of more subtle behavioral incompatibilities just from changing
> the order in which statics are initialized, and (what's more) making the
> order dynamically data dependent. The bugs that folks will run into
> from "going lazy" will be bootstrap ordering bugs, causing null
> pointer exceptions (typically) when one initializer needs access to
> a non-lazily initialized static in some other class.
>
> Bootstrap errors happen all the time when there are delicate inter-class
> initialization dependencies. Today we see it when static initializers
> recurse into themselves via another class. Tomorrow we will see it
> whenever there is a mix of lazy and non-lazy initialization.
>
> So, I don't buy that non-reservation of null is going to especially improve
> the user experience. It will remove one moderately sharp edge, leaving
> some sharper ones. I'm saying the reserved value is "moderately" sharp,
> because it is relatively easy to diagnose, compared with bootstrap ordering
> bugs, which are always non-local in nature.
>
> And, just to repeat another bit: We have already bitten the "no nulls" bullet
> with Optional. We are telling users that, for certain constructs, nulls are
> out of policy. That too could cause "all sorts of incompatibilities", making
> it hard to refactor to use the new feature (Optionals). So it feels like a
> defensible move here also. "Lazies are a language supported form of
> optionals which automatically change state from empty. You can't put
> nulls in them." What's hard about that? Especially if we make reflection
> and/or method handle versions which return an actual Optional if the
> user wants to do a non-triggering sense of the state.
>
> Anyway, on balance, I'd still prefer to make lazies like optionals, and
> then continue to align them that way when we get to non-static lazies
> and (if we go there) use-site lazies.
>
> I didn't say "if we go there" for non-static lazies because they are so
> freaking useful *today*, under the disguise of @Stable. We'll want to
> go there.
>
> HTH
>
> — John
More information about the valhalla-spec-observers
mailing list