notes from Valhalla meeting 5/24/17
john.r.rose at oracle.com
Wed Jun 21 23:48:04 UTC 2017
On Jun 21, 2017, at 12:03 PM, Frederic Parain <frederic.parain at oracle.com> wrote:
>> Can we get away with changing all static final fields to be lazily initialized without some explicit opt-in? It would be nice but it might induce subtle changes in behaviour and expectations (especially for where exceptions may occur).
> Whatever solution is chosen, it will induce changes in behavior and new places where exceptions
> can be thrown. Lazy initialized static fields allow us to support value types in static fields without
> having to modify the class loading/class initialization logic. Today if a class A has a static field
> of type class B, then class A can be initialized without having to load or initialized class B.
> If the rule is changed for value types, meaning that if class A has a static field of type value
> type V, then V has to be loaded and initialized before A can be initialized. And of course,
> loading and initialization of V can fail, leading to a new kind of initialization failure for A.
> The class loading/class initialization is way more complex than field access (at least in the VM),
> so we have to balance pros and cons of each solution.
What I'm thinking here is that the JVM tracks the first time any given CONSTANT_Fieldref
is resolved, whether or not the underlying class is initialized.
This means the JVM already has a "hook" per field reference to take a slow path
the first time the field is touched.
As far as opt-in is concerned, I think yes the language has to supply an opt-in.
Per-field lazy initialization is potentially very useful, but a cost is that users have
to look at their code and possibly refactor in order to make use of it.
(This is a theme with Java's initialization model: We ran out of automagic
ways to transparently speed up start-up years ago; users have to step up
but first we have to provide them with better tools and paradigms.)
At the JVM level (regardless of the language) I think the right answer is
to run a class's <clinit> before any static reference (including a lazy one).
Then, if the field itself is lazy, run its initializer.
The effect of this is that blocks of statics which cannot be decoupled from
each other stay normal, and get initialized before any lazy fields. Then the
lazy fields are initialized one at a time.
The above mentioned hook would work "as if" each lazy field were isolated
in its own nested class, inside the nominal field holder class. That's not hard
to implement, at all. And it's (probably) convenient to users, which is why
we're considering it. The AOT people found that the practice of initializing
*everything* if *anything* is touched made it hard to pick and choose among
initializer activities, with the result that it was hard to selectively "shake out"
only the initializer activities relevant to a particular application. We can do better.
More information about the valhalla-spec-observers