Fwd: Field initialization before 'super'

Brian Goetz brian.goetz at oracle.com
Fri Dec 15 21:08:03 UTC 2023


> The 'Field.setAccessible' method, which provides a standard API 
> mechanism for mutating final fields, considers strict finals to be 
> "non-modifiable", and will not enable reflective writes. (It already 
> does the same for record fields.)

We discussed this at the EG meeting and I'm still uncomfortable.

There are two not-completely-coincident sets of constraints:

  - Final instance fields that can be modified using setAccessible
  - Final instance fields that are trusted by the VM to stay constant

The former is specified as: final instance fields that are not in 
records and hidden classes, as well as the modularity constraint that 
prevent use of setAccessible in the absence of an "opens" edge (see 
AccessibleObject::checkCanSetAccessible).

The latter is a larger and somewhat more embarassing set: hidden 
classes, box classes, record classes, String, atomic field updaters, and 
a whitelisted set of packages (java.lang, java.lang.{invoke,reflect}, 
sun.invoke, jdk.internal.{reflect,foreign.layout,foreign,vm.vector}, 
jdk.incubator.vector (except for the weird in/out fields in System).  
Plus a flag to just turn on "trust them all, except the weird ones in 
System".

The former is specified through JDK specifications; the latter is a VM 
implementation detail that conservatively gives up optimization when we 
cannot prove that initialization is race-free.

Adding "value classes" to both lists seems reasonable.  Driving towards 
fewer modifiable final fields is a desirable goal; driving towards all 
final fields being trustable is also.

But this proposal also adds another entry to both lists: "final fields 
whose initialization precedes the super-call in all constructors."  This 
is not an easily describable property of the programming model, and it 
is pretty hard to explain why this is relevant.  Their presence on the 
first list may show up as weird breakage with existing frameworks under 
harmless-looking refactorings.  Plus, since we don't have a reasonable 
description for these fields at the language level (unlike "fields in 
records, hidden classes, or value classes"), it's hard to even talk about.

The stated purpose of the setAccessible loophole is deserialization; the 
existence of the non-trusting of final fields is due to the possibility 
that the JIT might inline the wrong value, either due to races (if the 
field is set after this escapes) or setAccessible shenanigans.

On the other hand, I think we all agree that we don't want a 
`really-final-i-mean-it` modifier on fields, and that if we'd like for 
most classes to be strictly initialized, then having a strict modifier 
on classes/ctors is another "wrong default".

tl;dr: I think the "strict field" formulation beyond that needed for 
value classes needs some more bake time.


More information about the valhalla-spec-experts mailing list