JDK-8242578 : VM support for sealed classes
  • Type: CSR
  • Component: hotspot
  • Sub-Component: runtime
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 15
  • Submitted: 2020-04-13
  • Updated: 2020-06-01
  • Resolved: 2020-05-20
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Introduce a PermittedSubclasses attribute in the class file format, so that the JVM can implement the sub-classing semantics of sealed classes.

Problem
-------

Sealed classes ([JEP 360][1]) are a preview feature of Java SE 15. The JVM will need to enforce the sub-classing semantics of sealed classes.

Solution
--------

A PermittedSubclasses attribute will be defined in the ClassFile format, containing information about which classes can extend or implement the class or interface containing the attribute.  The JVM will use the attribute's contents to ensure that only those classes and interfaces named in the PermittedSubclasses attribute can extend or implement that class.  Additionally, the extending (or implementing) class must have the same class loader and be in the same module as its sealed super class.

The format of the PermittedSubclasses attribute is checked even if no classes or interfaces are loaded that extend or implement the class.  The checking is done at class load time, and is similar to format checking of attributes such as NestMembers. For example, the JVM checks that the attribute's constant pool indexes are valid and that the PermittedSubclasses attribute occurs at most once per-class.

Note that the PermittedSubclasses attribute could potentially be useful in other ways, for example, in determining if a class or interface is a sealed class.

Specification
-------------

Java Virtual Machine Spec changes for the PermittedSubclasses attribute are attached.  Please note that JVM Spec section 5.3 is still under review by the expert group, and may change.


  [1]: https://bugs.openjdk.java.net/browse/JDK-8227043
Comments
[~dholmes] Thanks for the pointer. I've made a note to look again at this part of the JLS for the next preview.
01-06-2020

[~dlsmith] Thanks for the JEP updates.
31-05-2020

I've updated the JEP text to address David's feedback about accessibility/modules/packages and the lack of detail about JVM behavior. (Let's continue any further discussion about the JEP via email.)
29-05-2020

Dan, while the JEP talks about named and un-named modules the JLS changes do not. The proposed JLS update simply states in related to types in the "permits" clause that: > Every TypeName must denote a class type that is accessible (6.6 ���) So the types need not be in the same package, as long as the supertype (the sealed class) is public. **Edit: correction. As Gavin points out below the JLS does further restrict things based on whether in a named or un-named module. So Dan's additional editorial comment is correct.**
27-05-2020

[~gbierman] thank you for that I had obviously not spotted that later part. I'm finding the expression of this quite confusing. We initially state the class must be accessible but then impose further constraints that reject particular classes even if accessible. So the cumulative rules appear to be: - if the classes are in the same named module then they must be accessible to each other; otherwise - both classes (in un-named modules) must be in the same package (which implies the same un-named module) Accessibility in the same named module would, if I get this right, require both classes to be in the same package, or both classes to be public. This would almost be covered by the simple statement that the classes must be accessible to each other, but for some reason we are excluding relationships between public classes in different packages when not in a named-module. That seems somewhat arbitrary. This is more restrictive than the VM rule (which is perfectly fine) which allows for public classes in different packages regardless of whether they are in a named or un-named module. But the net result is that at present the JEP, the JLS changes and the JVMS changes, each say something slightly different.
27-05-2020

[~dholmes] If you are talking about 8.1.6 in the language spec, then a little further down from the sentence you quoted it also states: > If a sealed class C belongs to a named module, then every class named > in the permits clause of the declaration of C must belong to the same > module than C; otherwise a compile-time error occurs. > > If a sealed class C belongs to an unnamed module, then every class > named in the permits clause of the declaration of C must belong to the > same package than C; otherwise or a compile-time error occurs. Is that what you are looking for?
27-05-2020

In response to David's feedback, I've added this editorial note to the JVM spec change document (it will appear in future publications of the document): "These restrictions guarantee that an entry in `PermittedSubclasses` of the superclass will resolve to *C*. (We don't actually resolve the reference to *C*, because doing so would prompt a circularity, since derivation of *C* hasn't yet completed.)" "The Java language has an additional requirement that, if the classes belong to an unnamed module, they must both be in the same package. This encourages programmers to use the feature appropriately (they shouldn't try to spread a sealed hierarchy across different maintenance domains), but is not the sort of fundamental restriction the JVM needs to enforce. So another language or bytecode generator is free not to follow the package restriction."
27-05-2020

Moving this CSR to Approved, with comments. The primary material evaluated in the CSR process are the specifications submitted as part of the CSR. Any corresponding JEP is supplementary material from a CSR perspective, especially as JEPs can by design change at anytime while a CSR is evaluating a particular snap shot of a feature for inclusion in the platform. Inconsistencies between a JEP and its CSRs should be resolved of course. To make sure there is no misunderstanding, for "Please note that JVM Spec section 5.3 is still under review by the expert group, and may change." note that the JVM changes that are approved by virtue of this CSR are the ones that were submitted in this CSR. If there are further JVM changes in semantics from expert group feedback or code review, or other route, either this CSR should be withdraw, updated with an explanatory comment, and re-finalized for re-review, or a second CSR with the change in question should be filed.
20-05-2020

Hi Dan, the JEP certainly needs to be self-consistent in regards to those two sections of text: "same package" and "accessible" are not equivalent requirements. Further, if the runtime constraints differ from the compile-time constraints then it would be good to have the rationale for that captured somewhere - preferably (to me) the JEP but otherwise here in the CSR request. Though as far as I can see the JLS and JVMS proposals actually define similar "accessibility" rules (at least conceptually - a private nested class is not accessible outside its top-level class according to JLS, but in the JVM such a class has package access). That said, looking at the access related rules listed in the JVMS update: - The superclass belongs to a different run-time module than C. - C does not have its ACC_PUBLIC flag set (4.1) and the superclass belongs to a different run-time package than C. is this not equivalent to simply requiring that C is accessible to the superclass? Or is there some subtle case which is allowed by the 5.4.4 definition of accessibility that we wish to preclude with sealed types? Thanks.
20-05-2020

David, the JEP has limited discussion about JVM behavior���essentially, the "Compiled form of a sealed class" section. The parts you quoted are discussing compile-time language rules. (I think this is fine, since error conditions arising from inconsistent compilation or class file generation are not of interest to most readers.) You are right that the JEP's description of the language rules could be improved by making those two quoted parts consistent���specifically, by including the package restriction in #1 of the "imposes three constraints" discussion. (The module restriction is implied by #1 and #2���both classes must be able to reference each other.) In JVMS, there was a deliberate choice to exclude the package restriction. Instead, we effectively check that a PermittedSubclasses entry would resolve to the current class if we were to resolve it.
20-05-2020

I noticed an inconsistency in the JEP. The JEP Description initially states: > The classes specified by permits must be located near the superclass: > Either in the same module (if the superclass is in a named module) or > in the same package (if the superclass is in the unnamed module). but later it (and JVMS) states: > 1. Every permitted subclass must be accessible by the sealed class at compile time. This later statement allows for the subclass to be in the unnamed module and a different package to the superclass, provided the subclass is public. Edit: I should clarify that JVMS obviously refers to runtime so perhaps "at compile time" needs to be dropped as it requires accessibility at compile time and runtime.
19-05-2020

The changes in 5.3 do not contain semantic changes. The java language concept of non-sealed is not represented in the class file but could be determined using the java.lang.Class API's getInterfaces(), getSuperclass(), isSealed().
08-05-2020

Many of the the changes in 5.3 "Creation and Loading" look to be independent of sealing. Are there general semantic changes here? The Java language concept of non-sealed (JDK-8242521) has no representation in the class file?
08-05-2020

I've attached an updated spec change document. It includes a renaming of the attribute to PermittedSubclasses and revisions to the details of error checking (including cleanups of the surrounding creation/loading/derivation process).
07-05-2020

Moving to Provisional. I note that is some discussion about the naming of the attribute going on. It seems locally inconsistent for the attribute to be called PermittedSubtypes but it has a number_of_classes entry, as opposed to number_of_types, etc.
29-04-2020