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