<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body><div style="font-family: sans-serif;"><div class="markdown" style="white-space: normal;">
<p dir="auto">I have been wanting this feature for literally decades! I’m<br>
glad to see that its time is coming. My reasons:</p>
<ul>
<li>users can prove their code is free of certain init-races and NPEs</li>
<li>specifically, safe publication is safer</li>
<li>JIT no longer needs to do escape analysis to trust finals</li>
<li>stuff we had to do for ICs and lambdas is now generally available</li>
<li>we get closer to fixing certain race conditions in deserialization</li>
<li>we get closer to dealing with tech. debt from setAccessible</li>
</ul>
<p dir="auto">(The cost of this feature is cultural. Now users have two ways<br>
to do one task, initialize a final field: The improved way, and<br>
the usually-OK-but-sometimes-not way from literally Java 1.1.<br>
Which I defined. Which is why I’ve been wanting a fix for years.)</p>
<p dir="auto">I think it all works as you have framed it, Dan, with phase 1 quietly<br>
inferring strictness from constructor behavior. The user must opt into<br>
the changed field semantics by changing constructor code. There is no<br>
“nicer” way to opt into strictness, say on a whole-class basis, but<br>
that is clearly something that can follow later.</p>
<p dir="auto">The ACC_STRICT bit reflects the internal implementation change in the<br>
order of construction. Note: This change is not an API change, yet.<br>
Remember that reflection can observe private details like ACC_BRIDGE.</p>
<p dir="auto">(It may become an API change (with more explicit declaration) when<br>
we start interacting with Valhalla value classes. Spoiler: A<br>
value class, and all its supers, must have only strict final fields.)</p>
<p dir="auto">Even if we didn’t have ACC_STRICT in the classfile, the JVM could<br>
infer its setting by examining all relevant constructors. But it<br>
seems fair to put the bit into the classfile if the user goes to<br>
the trouble if refactoring construction order. (It cannot be<br>
inferred from legacy code, since the putfields are in the wrong<br>
places.) And for Valhalla we really do need ACC_STRICT, along<br>
with the related verifier rule to give it teeth.</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">ACC_STRICT implies ACC_FINAL and !ACC_STATIC. Verification ensures that a 'putfield' for an ACC_STRICT field of the current class never occurs after the 'super()' call. (Specifically, the receiver type for the putfield must be 'uninitializedThis', not a class type.)</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">Mentioning this entanglement between mode bits is a nerd-snipe. Let’s<br>
be careful here, for the sake of the future, that we don’t rule out<br>
strict statics, and strict non-finals. What I think we can and should<br>
do is roll out strictness ONLY for final non-statics, but reserve<br>
judgement about the other combinations.</p>
<p dir="auto">The combination of guarantees from (a) the existing language rules<br>
for finals and from (b) the new rules for strictness makes the following<br>
statement true for strict finals:</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; border-left-color: #999999; color: #999999;"><p dir="auto">NO-READ-BEFORE-INIT It is impossible for the JVM to issue a read of
<br>
a strict field until after the first write.</p>
</blockquote></blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">This is a broader statement than the fiddly details of strict finals.<br>
But it is equivalent, given (a) and (b), for non-static finals.<br>
(Prove me wrong!)</p>
<p dir="auto">Curiously, this statement could, in the future, be a contract for other<br>
kinds of fields besides non-static finals. And that is how nerd-snipes<br>
go viral.</p>
<p dir="auto">(And to my fellow nerds: PLEASE do not burden this JEP with all of the<br>
possible implications of that formulation of strictness. All in good time.)</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">3) Immutability of strict finals is a strong guarantee. JVM internals may treat strict final fields as truly immutable, without supporting any deopt paths when unexpected mutation occurs.</p>
<p dir="auto">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.)</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">There is some debt here to pay, because some framework authors will<br>
ask what is the alternative to the setAccessible we have taken away.<br>
But I think that can come later.</p>
<p dir="auto">One way to soften the blow would be to let the framework authors down<br>
more gently, and give some story for “well we allowed it up to now,<br>
and we will throw warnings and then errors at you soon, and you should<br>
learn the alternative tactics real soon”. The Java module system played<br>
these games, as does Panama in its native method access rules.</p>
<p dir="auto">But saying “it is turned off” is a start. The start of a conversation.</p>
<p dir="auto">What happens if (somehow) a framework author starts monkeying with<br>
final fields? This breaks the unique initialization condition for<br>
finals, since any final smashed by a framework presumably already<br>
had a perfectly legitimate value assigned by its constructor.<br>
(Or if it was Unsafe.allocateInstance, the legitimate value was<br>
the default value.) Really, such frameworks create potential<br>
violations of the NO-READ-BEFORE-INIT rule I stated above.</p>
<p dir="auto">By the way, the optimizing JIT secretly performs reads of fields,<br>
when it inspects live data and decides to constant fold it,<br>
or make other conclusions based on the live data. So even if<br>
the source code does not apparently commit read-before-init<br>
faults, the JIT might. It’s the JIT’s responsibility to<br>
be careful with such reads.</p>
<p dir="auto">One thing we might want to do is to add logic to setAccessible<br>
that throws away code that might have been optimized too<br>
confidently, since setAccessible(true) means there may be<br>
read-before-init hazards coming, on a particular field.<br>
This sort of thing has been prototyped in the past more<br>
than once, I think. It’s just hard to put the whole story<br>
together without the early-init of fields given by this JEP.</p>
<p dir="auto">But the easiest best starting point is to turn off setAccessible<br>
as much as possible.</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">Standard deserialization ensures strict finals are set, and so their values deserialized, before the object under construction is leaked to any user code. This probably means back references to an object from its own strict final fields are unsupported, and deserialize to 'null'. (Records already behave in this way.)</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">My nightmare about this has always been: Can I prove that the<br>
JIT will NEVER peek into an unfinished object, and draw conclusions<br>
from the uninitialized field contents? Such a proof seems tricky,<br>
given that the deserialization code makes no clear distinction<br>
(that the JIT can see) between under-construction objects and<br>
safe-to-publish objects. This is a long-standing technical debt<br>
in deserialization (all such frameworks).</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">Unsafe and JNI are capable of performing arbitrary, type-unsafe modifications to field storage. Clients who modify strict finals do so at their own risk, and JVM optimizations won't try to account for such usage.</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">Yep! If you use Unsafe or JNI to hack objects, you become a VM<br>
implementor. Don’t want that responsibility? Use a higher level<br>
API. (Such as record canonical constructors or TBD for strict<br>
fields or Valhalla values.)</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">That covers "phase 1" for this feature. Eventually, we'll want to address questions like
<br>
- What about fields with initializers?</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">(Choices there include “move the field initializers always”,<br>
“move initializers which are simple enough”, and “don’t use<br>
field initializers”. Dunno which combination wins.)</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">- Can I have my implicit 'super()' call go at the end of my constructor?</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">(Choices include, “sure, why not? we’ll pretend the super doesn’t do<br>
side effects”, or “we can somehow tell the super is safe”, or “nope,<br>
only for Valhalla value classes”, or “only if you opt in with a<br>
class-level keyword”. Again, who knows which one wins.)</p>
</div><div class="plaintext" style="white-space: normal;"><blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">- Can javac check for me that my fields are strict?</p>
</blockquote></div>
<div class="markdown" style="white-space: normal;">
<p dir="auto">(Choices include, “request checks with a class-level keyword”,<br>
or “only for Valhalla values”, or “use an annotation”. Today<br>
I find it kind of charming that an annotation might do the<br>
trick, at least before Valhalla. Something like @Override<br>
that merely observes and comments. It might even comment<br>
that you could put your super in a better place.)</p>
<p dir="auto">— John</p>
</div></div></body>
</html>