On Jun 21, 2017, at 12:03 PM, Frederic Parain <frederic.par...@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. — John