This document describes changes to the Java Virtual Machine Specification as modified by Class Loading Cleanup to support sealed types, a preview feature of Java SE 15. A sealed class or interface restricts extension and implementation to an enumerated set of authorized subclasses or subinterfaces. See JEP 360 for an overview of the feature.
Changes are described with respect to existing sections of the JVM Specification. New text is indicated like this and deleted text is indicated like this. Explanation and discussion, as needed, is set aside in grey boxes.
Chapter 4: The class
File Format
4.7 Attributes
Attributes are used in the ClassFile
, field_info
, method_info
, and Code_attribute
structures of the class
file format (4.1, 4.5, 4.6, 4.7.3).
All attributes have the following general format:
attribute_info {
u2 attribute_name_index;
u4 attribute_length;
u1 info[attribute_length];
}
For all attributes, the attribute_name_index
item must be a valid unsigned 16-bit index into the constant pool of the class. The constant_pool
entry at attribute_name_index
must be a CONSTANT_Utf8_info
structure (4.4.7) representing the name of the attribute. The value of the attribute_length
item indicates the length of the subsequent information in bytes. The length does not include the initial six bytes that contain the attribute_name_index
and attribute_length
items.
28 29 attributes are predefined by this specification. They are listed three times, for ease of navigation:
Table 4.7-A is ordered by the attributes' section numbers in this chapter. Each attribute is shown with the first version of the
class
file format in which it was defined. Also shown is the version of the Java SE Platform which introduced that version of theclass
file format (4.1).Table 4.7-B is ordered by the first version of the
class
file format in which each attribute was defined.Table 4.7-C is ordered by the location in a
class
file where each attribute is defined to appear.
Within the context of their use in this specification, that is, in the attributes
tables of the class
file structures in which they appear, the names of these predefined attributes are reserved.
Any conditions on the presence of a predefined attribute in an attributes
table are specified explicitly in the section which describes the attribute. If no conditions are specified, then the attribute may appear any number of times in an attributes
table.
The predefined attributes are categorized into three groups according to their purpose:
SixSeven attributes are critical to correct interpretation of theclass
file by the Java Virtual Machine:ConstantValue
Code
StackMapTable
BootstrapMethods
NestHost
NestMembers
PermittedSubtypes
In a
class
file whose version number is v, each of these attributes must be recognized and correctly read by an implementation of the Java Virtual Machine if the implementation supports version v of theclass
file format, and the attribute was first defined in version v or earlier of theclass
file format, and the attribute appears in a location where it is defined to appear.Nine attributes are not critical to correct interpretation of the
class
file by the Java Virtual Machine, but are either critical to correct interpretation of theclass
file by the class libraries of the Java SE Platform, or are useful for tools (in which case the section that specifies an attribute describes it as "optional"):Exceptions
InnerClasses
EnclosingMethod
Synthetic
Signature
SourceFile
LineNumberTable
LocalVariableTable
LocalVariableTypeTable
In a
class
file whose version number is v, each of these attributes must be recognized and correctly read by an implementation of the Java Virtual Machine if the implementation supports version v of theclass
file format, and the attribute was first defined in version v or earlier of theclass
file format, and the attribute appears in a location where it is defined to appear.Thirteen attributes are not critical to correct interpretation of the
class
file by the Java Virtual Machine, but contain metadata about theclass
file that is either exposed by the class libraries of the Java SE Platform, or made available by tools (in which case the section that specifies an attribute describes it as "optional"):SourceDebugExtension
Deprecated
RuntimeVisibleAnnotations
RuntimeInvisibleAnnotations
RuntimeVisibleParameterAnnotations
RuntimeInvisibleParameterAnnotations
RuntimeVisibleTypeAnnotations
RuntimeInvisibleTypeAnnotations
AnnotationDefault
MethodParameters
Module
ModulePackages
ModuleMainClass
An implementation of the Java Virtual Machine may use the information that these attributes contain, or otherwise must silently ignore these attributes.
Table 4.7-A. Predefined class
file attributes (by section)
Attribute | Section | class file |
Java SE |
---|---|---|---|
ConstantValue |
4.7.2 | 45.3 | 1.0.2 |
Code |
4.7.3 | 45.3 | 1.0.2 |
StackMapTable |
4.7.4 | 50.0 | 6 |
Exceptions |
4.7.5 | 45.3 | 1.0.2 |
InnerClasses |
4.7.6 | 45.3 | 1.1 |
EnclosingMethod |
4.7.7 | 49.0 | 5.0 |
Synthetic |
4.7.8 | 45.3 | 1.1 |
Signature |
4.7.9 | 49.0 | 5.0 |
SourceFile |
4.7.10 | 45.3 | 1.0.2 |
SourceDebugExtension |
4.7.11 | 49.0 | 5.0 |
LineNumberTable |
4.7.12 | 45.3 | 1.0.2 |
LocalVariableTable |
4.7.13 | 45.3 | 1.0.2 |
LocalVariableTypeTable |
4.7.14 | 49.0 | 5.0 |
Deprecated |
4.7.15 | 45.3 | 1.1 |
RuntimeVisibleAnnotations |
4.7.16 | 49.0 | 5.0 |
RuntimeInvisibleAnnotations |
4.7.17 | 49.0 | 5.0 |
RuntimeVisibleParameterAnnotations |
4.7.18 | 49.0 | 5.0 |
RuntimeInvisibleParameterAnnotations |
4.7.19 | 49.0 | 5.0 |
RuntimeVisibleTypeAnnotations |
4.7.20 | 52.0 | 8 |
RuntimeInvisibleTypeAnnotations |
4.7.21 | 52.0 | 8 |
AnnotationDefault |
4.7.22 | 49.0 | 5.0 |
BootstrapMethods |
4.7.23 | 51.0 | 7 |
MethodParameters |
4.7.24 | 52.0 | 8 |
Module |
4.7.25 | 53.0 | 9 |
ModulePackages |
4.7.26 | 53.0 | 9 |
ModuleMainClass |
4.7.27 | 53.0 | 9 |
NestHost |
4.7.28 | 55.0 | 11 |
NestMembers |
4.7.29 | 55.0 | 11 |
PermittedSubtypes |
4.7.30 | 59.65535 | 15 |
Table 4.7-B. Predefined class
file attributes (by class
file format)
Attribute | class file |
Java SE | Section |
---|---|---|---|
ConstantValue |
45.3 | 1.0.2 | 4.7.2 |
Code |
45.3 | 1.0.2 | 4.7.3 |
Exceptions |
45.3 | 1.0.2 | 4.7.5 |
SourceFile |
45.3 | 1.0.2 | 4.7.10 |
LineNumberTable |
45.3 | 1.0.2 | 4.7.12 |
LocalVariableTable |
45.3 | 1.0.2 | 4.7.13 |
InnerClasses |
45.3 | 1.1 | 4.7.6 |
Synthetic |
45.3 | 1.1 | 4.7.8 |
Deprecated |
45.3 | 1.1 | 4.7.15 |
EnclosingMethod |
49.0 | 5.0 | 4.7.7 |
Signature |
49.0 | 5.0 | 4.7.9 |
SourceDebugExtension |
49.0 | 5.0 | 4.7.11 |
LocalVariableTypeTable |
49.0 | 5.0 | 4.7.14 |
RuntimeVisibleAnnotations |
49.0 | 5.0 | 4.7.16 |
RuntimeInvisibleAnnotations |
49.0 | 5.0 | 4.7.17 |
RuntimeVisibleParameterAnnotations |
49.0 | 5.0 | 4.7.18 |
RuntimeInvisibleParameterAnnotations |
49.0 | 5.0 | 4.7.19 |
AnnotationDefault |
49.0 | 5.0 | 4.7.22 |
StackMapTable |
50.0 | 6 | 4.7.4 |
BootstrapMethods |
51.0 | 7 | 4.7.23 |
RuntimeVisibleTypeAnnotations |
52.0 | 8 | 4.7.20 |
RuntimeInvisibleTypeAnnotations |
52.0 | 8 | 4.7.21 |
MethodParameters |
52.0 | 8 | 4.7.24 |
Module |
53.0 | 9 | 4.7.25 |
ModulePackages |
53.0 | 9 | 4.7.26 |
ModuleMainClass |
53.0 | 9 | 4.7.27 |
NestHost |
55.0 | 11 | 4.7.28 |
NestMembers |
55.0 | 11 | 4.7.29 |
PermittedSubtypes |
59.65535 | 15 | 4.7.30 |
Table 4.7-C. Predefined class
file attributes (by location)
Attribute | Location | class file |
---|---|---|
SourceFile |
ClassFile |
45.3 |
InnerClasses |
ClassFile |
45.3 |
EnclosingMethod |
ClassFile |
49.0 |
SourceDebugExtension |
ClassFile |
49.0 |
BootstrapMethods |
ClassFile |
51.0 |
Module , ModulePackages , ModuleMainClass |
ClassFile |
53.0 |
NestHost , NestMembers |
ClassFile |
55.0 |
PermittedSubtypes |
ClassFile |
59.65535 |
ConstantValue |
field_info |
45.3 |
Code |
method_info |
45.3 |
Exceptions |
method_info |
45.3 |
RuntimeVisibleParameterAnnotations , RuntimeInvisibleParameterAnnotations |
method_info |
49.0 |
AnnotationDefault |
method_info |
49.0 |
MethodParameters |
method_info |
52.0 |
Synthetic |
ClassFile , field_info , method_info |
45.3 |
Deprecated |
ClassFile , field_info , method_info |
45.3 |
Signature |
ClassFile , field_info , method_info |
49.0 |
RuntimeVisibleAnnotations , RuntimeInvisibleAnnotations |
ClassFile , field_info , method_info |
49.0 |
LineNumberTable |
Code |
45.3 |
LocalVariableTable |
Code |
45.3 |
LocalVariableTypeTable |
Code |
49.0 |
StackMapTable |
Code |
50.0 |
RuntimeVisibleTypeAnnotations , RuntimeInvisibleTypeAnnotations |
ClassFile , field_info , method_info , Code |
52.0 |
4.7.30 The PermittedSubtypes
Attribute
The PermittedSubtypes
attribute is a variable-length attribute in the attributes
table of a ClassFile
structure. If a class or interface has a PermittedSubtypes
attribute, any class or interface that attempts to extend or implement it must be named by the attribute (5.3.5).
In the Java Programming Language, there is a
sealed
modifier to indicate a class or interface that constrains extension in this way. In the class file, there is noACC_SEALED
flag. Instead, asealed
class or interface is indicated by the presence of thePermittedSubtypes
attribute.
There may be at most one PermittedSubtypes
attribute in the attributes
table of a ClassFile
structure whose ACC_FINAL
flag is not set (4.1). If the ACC_FINAL
flag is set, then the ClassFile
structure must not have a PermittedSubtypes
attribute.
We treat sealed as distinct from final—a sealed class has an enumerated list of designated subclasses, while a final class has no subclasses. Thus, a ClassFile
structure may have a PermittedSubtypes
attribute, or may have its ACC_FINAL
flag set, but not both.
Alternatively, we could have let the PermittedSubtypes
attribute refine the ACC_FINAL
flag—reinterpreting "final" to mean "can't be extended, except for authorized subclasses". But doing so risks disrupting consumers of class files that have long assumed "final" means "has 0 subclasses" and that interfaces cannot be final.
The PermittedSubtypes
attribute has the following format:
PermittedSubtypes_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 number_of_classes;
u2 classes[number_of_classes];
}
The items of the PermittedSubtypes_attribute
structure are as follows:
- attribute_name_index
The value of the
attribute_name_index
item must be a valid index into theconstant_pool
table. Theconstant_pool
entry at that index must be aCONSTANT_Utf8_info
structure (4.4.7) representing the string "PermittedSubtypes
".- attribute_length
The value of the
attribute_length
item indicates the length of the attribute, excluding the initial six bytes.- number_of_classes
The value of the
number_of_classes
item indicates the number of entries in theclasses
array.- classes[]
Each value in the
classes
array must be a valid index into theconstant_pool
table. Theconstant_pool
entry at that index must be aCONSTANT_Class_info
structure (4.4.1) representing a class or interface which is authorized to extend or implement the current class or interface.The
classes
array is consulted when a class or interface that attempts to directly extend or implement the current class or interface is created (5.3.5). Array items that do not attempt to directly extend or implement the current class or interface are ignored.
Chapter 5: Loading, Linking, and Initializing
5.3 Creation and Loading
5.3.5 Deriving a Class from a class
File Representation
The following steps are used to derive a nonarray class or interface C denoted by N using loader L from a purported representation in class
file format.
First, the Java Virtual Machine determines whether the attempt to derive a class or interface named N for class loader L is invalid. If so, derivation throws a
LinkageError
.An attempt to derive a class or interface named N for class loader L is invalid if one of the following are true:
L has already been recorded as as an initiating loader of a class or interface named N.
L is not the bootstrap class loader (5.3) and N is the reserved name
java/lang/Object
.
The second case, combined with restrictions in 4.1, ensures that there is only one root of the class hierarchy, and the name
java/lang/Object
can reliably be used to refer to it.The Java SE API enforces additional security restrictions that prevent unauthorized attempts to load classes in certain packages, including
java.*
.Otherwise, the Java Virtual Machine attempts to parse the purported representation. However, the purported representation may not in fact be a valid representation of C.
This phase of derivation must detect the following errors:
If the purported representation provides a major and minor version number in its 5th through 8th bytes (4.1), but the version number is not supported by this Java Virtual Machine implementation, derivation throws an instance of
UnsupportedClassVersionError
.UnsupportedClassVersionError
, a subclass ofClassFormatError
, was introduced to enable easy identification of aClassFormatError
caused by an attempt to load a class whose representation uses an unsupported version of theclass
file format. In JDK 1.1 and earlier, an instance ofNoClassDefFoundError
orClassFormatError
was thrown in case of an unsupported version, depending on whether the class was being loaded by the system class loader or a user-defined class loader.Otherwise, if the purported representation is not a
ClassFile
structure (4.1, 4.8), derivation throws an instance ofClassFormatError
.Otherwise, if the purported representation does not actually represent a class or interface named N, derivation throws an instance of
NoClassDefFoundError
or an instance of one of its subclasses.This occurs when the purported representation has either a
this_class
item which specifies a name other than N, or anaccess_flags
item which has theACC_MODULE
flag set.
If C has a direct superclass, the symbolic reference from C to its direct superclass is resolved using the algorithm of 5.4.3.1. Note that if C is an interface it must have
Object
as its direct superclass. OnlyObject
has no direct superclass.Any exceptions that can be thrown due to class or interface resolution can be thrown as a result of this phase of derivation. In addition, this phase of derivation must detect the following errors:
If the attempt to resolve the direct superclass leads to the current thread attempting to recursively derive a class named N using loader L, derivation throws a
ClassCircularityError
.Otherwise, if the class or interface named as the direct superclass of C is an interface or a
final
class, derivation throws anIncompatibleClassChangeError
.Otherwise, if the class named as the direct superclass of C has a
PermittedSubtypes
attribute (4.7.30), at least one entry in theclasses
table of the superclass'sPermittedSubtypes
attribute must reference a class or interface with name N. If not, derivation throws anIncompatibleClassChangeError
.To ensure that the name N appearing in the superclass refers to C, an attempt is made, using the defining class loader of the superclass, to create a class or interface denoted by N. The attempt must lead to the current thread attempting to recursively derive a class or interface named N using loader L; the attempt is then abandoned. If the recursive attempt at derivation does not occur, derivation throws an
IncompatibleClassChangeError
.Otherwise, if C is a class and some non-
static
method declared in C can override (5.4.5) afinal
, non-static
method declared in a superclass of C, derivation throws anIncompatibleClassChangeError
.
If C has any direct superinterfaces, the symbolic references from C to its direct superinterfaces are resolved using the algorithm of 5.4.3.1.
Any exceptions that can be thrown due to class or interface resolution can be thrown as a result of this phase of derivation. In addition, this phase of derivation must detect the following errors:
If the attempt to resolve a direct superinterface leads to the current thread attempting to recursively derive a class named N using loader L, derivation throws a
ClassCircularityError
.Otherwise, if any of the classes or interfaces named as direct superinterfaces of C is not in fact an interface, derivation throws an
IncompatibleClassChangeError
.Otherwise, for each direct superinterface, if the superinterface has a
PermittedSubtypes
attribute (4.7.30), at least one entry in theclasses
table of the superinterface'sPermittedSubtypes
attribute must reference a class or interface with name N. If not, derivation throws anIncompatibleClassChangeError
.To ensure that the name N appearing in the superinterface refers to C, an attempt is made, using the defining class loader of the superclass, to create a class or interface denoted by N. The attempt must lead to the current thread attempting to recursively derive a class or interface named N using loader L; the attempt is then abandoned. If the recursive attempt at derivation does not occur, derivation throws an
IncompatibleClassChangeError
.
If, since step 1, in another thread, the Java Virtual Machine has marked a class or interface named N as having L as its defining class loader, that class or interface is the result of class derivation, and the class or interface derived in steps 1-4 is discarded.
Otherwise, the class or interface derived in steps 1-4 is the result of class derivation, and the Java Virtual Machine marks C as having L as its defining class loader and records that L is an initiating loader of C (5.3.4).