JDK-8300786 - No longer require super() and this() to appear first in a constructor

Archie Cobbs archie.cobbs at gmail.com
Tue Jan 31 20:45:02 UTC 2023


Hi folks,

I'm working on this issue:

JDK-8194743 <https://bugs.openjdk.org/browse/JDK-8194743> - Permit
additional statements before this/super in constructors.

Obviously this change requires a JEP, and so we have this JEP draft for
review:

JDK-8300786 <https://bugs.openjdk.org/browse/JDK-8300786> - No longer
require super() and this() to appear first in a constructor

Here's a summary of the discussion that's occurred so far on amber-dev...

People are agreeable with the general idea of relaxing the JLS rules here,
but of course the devil is in the details.

The current JMVS gives constructors a lot more flexibility wrt. superclass
initialization than the JLS:

   - Multiple invocations of this() and/or super() may appear in a
   constructor, as long as on any code path there is exactly one invocation
   - Arbitrary code may appear before this()/super(), as long as that code
   doesn't reference the instance under construction, with an exception carved
   out for field assignments
   - However, invocations of this()/super() may not appear within a try { }
   block (i.e., within a bytecode exception range)

So the question becomes, how far to push the JLS up against these limits,
or conceivably even past them (i.e., relaxing both the JLS and JVMS).

Roughly in order of increasing aggressiveness, here are some of the options
that have been discussed (these are not all mutually exclusive):

   1. Permit "static context" code prior to super()/this(), but otherwise
   super()/this() still must occur exactly once and as a top-level
   statement in the constructor.
   2. Allow arbitrary appearances of super()/this() in constructors, and
   apply DA/DU analysis like a blank final field to verify exactly one ever
   gets invoked
   3. Also allow assignments to fields declared in the same class prior to
   super()/this()
   4. (JVMS mod required) Allow super()/this() within try { } blocks, as
   long as within any catch block execution completes abruptly with another
   throw

#1 is the minimal change. It accomplishes the basic goal of allowing
"housekeeping" prior to superclass initialization. It also requires fairly
minimal JLS changes (drafted already in the JEP).

#2 is arguably a more natural way to relax things, but beyond #1 it
addresses a fairly niche set of incremental use cases, and would have a
large impact on the JLS for that relatively meager marginal return.

#3 is debatable. The 'this' escape problem (e.g., HashSet(Collection)) is
very real and Java provides victim subclasses with no easy way to avoid it.
This feature would make it easy to avoid. However, it has a conceptual
cost. Allowing field assignments, but no other 'this' references, is an
obvious hack/exception to the rules. To be sure, there are practical
reasons for it (which is why it was added to the JVMS in the first place),
but from a language design point of view it left some people a little
uneasy. It's a classic beauty vs. function debate.

#4 is kind of a related side issue that came up. It could stand alone as an
independent change. I'd be curious to hear people's opinions here. It would
allow you to catch exceptions thrown by a super()/this() call as long as
you then (re)throw some exception. It would also fix a difficulty for
bytecode weaving tools that do things like measure method execution times.

One could also argue that by making super()/this() calls more like normal
method calls (less "special"), items #2 and #4 would improve language
harmony, etc.

In any case, the current JEP draft takes the conservative route and opts
for #1 only.

Thanks,
-Archie

-- 
Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20230131/494912c2/attachment.htm>


More information about the amber-spec-experts mailing list