Draft Spec for Flexible Constructor Bodies (JEP 513)
Dan Smith
daniel.smith at oracle.com
Mon Apr 28 20:01:06 UTC 2025
> On Apr 24, 2025, at 6:34 AM, Remi Forax <forax at univ-mlv.fr> wrote:
>
>> Perhaps we should be asking: who will emit the ACC_STRICT_INIT flag, and when?
>
> yes, making the early field initialization part of FCB muddy our chances to later uses early initialization as a signal for the compiler to declare the field as ACC_STRICT_INIT.
> So i would prefer to have a real plan on how Java will use ACC_STRICT_INIT. For now, we have not ruled out to use early initialization as a signal, so i would like to keep that option open, even if that means going back to the original proposal of FCB, and only releasing that.
Let me clarify how we've been thinking in recent Valhalla work about the path toward an eventual strict-by-default world in the language:
1) With value classes, we introduce the concept of strictly-initialized fields in the JVM, enforce rules that value class sources require early initialization of their fields, and provide an "early-by-default" interpretation of these classes (early instance field initializers, implicit 'super()' at the end of constructors). Potentially, we can also subject record classes to these behaviors, with some small compatibility risk. [See https://openjdk.org/jeps/401#Value-object-initialization]
2) At the same time, we introduce some *warnings* to encourage a style of programming in identity classes that could support early-by-default compilation in the future. [See https://openjdk.org/jeps/401#Encouraging-early-initialization-of-identity-classes]
3) At some later point, we provide a language feature (mechanism TBD) to allow identity classes to opt in to the value class early-by-default rules. In a class that opts in, a field that is early-initialized is treated as ACC_STRICT_INIT, and a field that is late-initialized is not. (It might be an error or warning to try to mix initialization timings of a single field.)
Where does support for early assignment in constructor bodies fit in? It's a hard prerequisite to (1), because that is the only way to initialize a value class field. It's also important for (2), because one way to address warnings about 'this' dependencies is to add a 'super()' call to the constructor, and then put the 'this'-dependent code after that call (but keep the rest of the code early).
Note that (2) has no semantic impact, so it's something we can readily impose on every class. And then the idea is that (3) allows programmers to opt in to subtly different semantics (like the memory model effects you've illustrated); a program that has addressed the warnings by then won't need to make any additional source changes.
Of course this is not the only possible way to approach the problem, but there are some good reasons to arrange things like this:
- (1) comes with early initialization requirements, but we don't want to tie the semantic changes of (3) to getting value classes out the door. Frankly, (3) is a can of worms and I'm not sure where it will lead. So there needs to be some space between (1) and (3).
- (1) encourages class authors to think about construction timing and 'this' dependencies, and so it's a good opportunity to get them to consider those things throughout their code—hence tying (1) and (2) together.
(One piece of this that isn't clear to me, and that we need to discuss further, is where '!'-typed fields fit in—they also require early initialization and ACC_STRICT_INIT. Maybe using '!' on a field is one form of the opt-in described in (3). Or maybe that's too indirect. TBD...)
More information about the amber-spec-observers
mailing list