Loosening requirements for super() invocation
Brian Goetz
brian.goetz at oracle.com
Tue Nov 1 21:30:24 UTC 2022
> First of all, when should this rule apply?
>
> At any point in a constructor (one that successfully compiles), the
> new object is always definitively in one of three states:
>
> State 0: neither super() nor this() has been invoked; neither the
> superclass nor this class are initialized
> State 1: super() has been invoked, so the superclass is initialized,
> but at least one final field in this class has not been initialized
> State 2: super() has been invoked and all final fields in this class
> have been initialized
>
> BTW, the current state is easily tracked within the existing DA/DU
> analysis of the prototype patch.
>
> The possible state transitions are:
>
> - super() takes you from:
> - State 0 → State 1 if there remain any uninitialized final fields
> - State 0 → State 2 if there are no remaining uninitialized final fields
> - this() takes you from State 0 → State 2
> - Initializing the last final field takes you from:
> - State 0 → State 0
> - State 1 → State 2
>
> Presumably the 'this' escape analysis should only apply in State 1.
> This is when the object is vulnerable because it's half initialized.
In actuality, `this` can escape in any of the states; escaping means
that `this` is exposed before the return from the constructor. (Even the
very last line of the constructor is suspect. A class could have
subclasses, which means we're still in "the middle" of the subclass
constructor, and even for a final class, the write barrier does not get
emitted until after the constructor completes.)
All of this said, we should probably tune warnings to the various
states, since escape during State 0 is "even worse" than escape during
State 2. And we should add:
State 3: we're still in the constructor
In any case, let's start with the strictest view and work backwards to
relaxation. The receiver may escape if:
- a non-final instance method is invoked (*)
- an instance method declared in a superclass is invoked
- the variable `this` is used for anything other than field access
We should analyze not only constructor code, but instance initializer
blocks and instance field initializers as well. We can exclude final
instance methods declared in the same class if the same analysis of the
method (recursively) shows no escape of `this` (this is the * in the
first bullet above.)
Inner class creation is a similar story as calling final methods in the
same class; we can do a similar analysis of the inner class constructor
to verify non-escape.
> For the meaning of "known to be equal to 'this'", we would be limited
> in our ability to infer it in the usual ways (Turing complete, blah
> blah), so you'd still be able to evade the warning e.g.:
For this to happen, `this` must have already escaped or have been
assigned to another variable. The above already detects this.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20221101/c0f08192/attachment.htm>
More information about the amber-dev
mailing list