This task summarizes the JVM changes introduced by the parent JEP, JDK-8317765. All features are activated by the `--enable-preview` launcher option.
### ImplicitCreation attribute
The `ImplicitCreation` attribute may be applied at the `ClassFile` level to a class to opt in to implicit zero instance creation.
ImplicitCreation_attribute {
u2 attribute_name_index;
u4 attribute_length;
}
Format checking fails if an `ImplicitCreation` attribute is applied to an identity class or any interface.
There is no requirement that an `<init>` method of the class matches the Java language requirements for an implicit constructor. Implicit creation in the JVM does not make use of `<init>` methods.
The _zero instance_ of a concrete value class that has an `ImplicitCreation` attribute is a class instance with all instance fields set to their default values. The JVM may freely "create" this instance whenever necessary.
### CheckedType constants
A "`CheckedType` constant" is defined as a `CONSTANT_Dynamic` constant whose bootstrap method belongs to the class 'java.lang.runtime.CheckedTypeBootstraps` and whose `NameAndType` must have a the descriptor `Ljava/lang/reflect/CheckedType;`. (In the future, either the bootstrap restriction will be dropped, or a dedicated constant form will be defined.)
(TODO: do we need to impose class loader constraints on these types?)
Checked types may be represented internally in whatever way is convenient; for now, a checked type constant represents one of:
- A reference class type (not a primitive type)
- A null-restricted value class type, where the value class has an `ImplicitCreation` attribute
As for any `Dynamic` constant, an `ldc` may refer to a `CheckedType` constant.
### Casts
The `checkcast` instruction may opt to refer to a `CheckedType` constant instead of a `Class` constant.
For verification, the output type of the instruction is the same as its input type, no matter what kind of `CheckedType` constant is denoted. (A traditional cast using a `Class` constant must be used to communicate type assertions to the verifier.)
At run time, the `CheckedType` constant is first resolved (even if a `null` is on the stack). Then the checked type is enforced, possibly failing with a `ClassCastException` or a `NullPointerException`.
(The `instanceof` instruction may _not_ refer to a `CheckedType` constant, since `Class` constants already produce `false` for null inputs.)
### Arrays
The `anewarray` instruction may opt to refer to a `CheckedType` constant instead of a `Class` constant. The checked type denotes the array's component type. The array components are initialized to the component type's default value; if the component type is a null-restricted type, the default value is the zero instance of the named class.
Array stores (e.g., via `aastore`) check the component type, as usual, and throw `ArrayStoreException` if the input does not satisfy the checked type.
There is no JVM type to represent `Foo![]` (at least for now); this erases to the type `Foo[]`.
There is no change to the `multianewarray` instruction. A multi-dimensional array with null-restricted elements must be constructed manually.
Invocations of the `clone` method of an array type should create a copy that uses the same `CheckedType` as the original.
### Fields
The `FieldCheckedType` attribute may be applied to a `field_info` structure to indicate a dynamically-checked type of the field.
FieldCheckedType_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 checkedtype_index;
}
The `checkedtype_index` must refer to a `CheckedType` constant.
If a checked type is present, the initial value of the field, as set by preparation, is the checked type's default value. For a null-restricted type, this is the zero instance of the named class.
Field writes (e.g., via `putfield` or `putstatic`) dynamically check the checked type and throw `FieldStoreException` if the input does not satisfy the checked type.
The checked type of a field is distinct from its descriptor type, which is enforced by linkage rather than dynamic checks. The descriptor type and checked type need not be related.
### Atomicity
A null-restricted field or array storing value objects must typically ensure that the data will be updated atomically.
A value class may optionally implement the `LooselyConsistentValue` interface (either directly or indirectly), and if so, the JVM is free to handle null-restricted fields and arrays of that type in a way that does not guarantee atomic updates.
### Class loading
Class loading fails for a class with an `ImplicitCreation` attribute if any of:
- The superclass is not `Object` and does not have an `ImplicitCreation` attribute
- The zero instance of the class contains itself (via a circularity in the `FieldCheckedType` attributes of instance fields)
When preview features are enabled, the following non-preview classes are treated as if they had `ImplicitCreation` set:
- java.lang.Number
- java.lang.Record
- All 8 wrapper classes
- java.util.Optional
### Initialization
The `anewarray` instruction requires initialization of the component type's class if the component type is a null-restricted type.
When initializing a class, any other class that appears as a null-restricted checked type of one of the first class's fields must recursively be initialized.
### Runtime checking
Casts, array writes, and field writes may perform null checks and class checks, as described above. These are internal JVM operations—no Java code (such as a 'CheckedType.cast' invocation) is executed.
In C2, the type system is able to track these properties (including nullness), and checks that can be statically proven to be redundant are skipped at run time.
### Object encodings
In *this release* of HotSpot, value objects stored in null-restricted fields and arrays encoded as follows. (These details are subject to change in future releases.)
- If the object's fields can be stored in an atomic word size (e.g., 64 bits), null-restricted fields and arrays encode the object in a bit vector of that size, and reads and writes are performed atomically.
- Otherwise, if the value class implements `LooselyConsistentValue` (directly or indirectly), and the field is not `volatile`, and the number/size of fields is within some threshold, null-restricted fields and arrays encode the object as a sequence of field values, each of which is read/written independently. Some extra padding may be inserted in arrays to achieve good alignment.
- Otherwise, the object is encoded as a regular heap object.
Null-restricted arrays are initialized eagerly. If the array is flattened, memory is set to zeroes, and those zero bits are interpreted as the zero instance of the class. If the array is not flattened, a zero instance of the class is located or allocated, and each component is set to a pointer to that instance.
Null-restricted fields are always initialized with zeroes. If the field is not flattened, then this is a lazy initialization strategy: the bits encode a `null` pointer, which is detected by the first field read (`getfield`, `getstatic`) and replaced at that point with an appropriate pointer to a zero instance.
### Signature attributes
The syntax of the `Signature` attribute is enhanced to denote null-restricted Java language types by appending a `!` symbol to a class type:
ClassTypeSignature:
L [PackageSpecifier] SimpleClassTypeSignature {ClassTypeSignatureSuffix} [ ! ] ;
Note that the ! appears _after_ any type arguments rather than _before_ them, to avoid disrupting the structure of `SimpleClassTypeSignature` and `ClassTypeSignatureSuffix`. (A '!' would not make sense on an outer class type that qualifies an inner class type.)
### Other JVM tools and APIs
- `java.lang.invoke` may need to implement the new array and field storage checks
- `javap` displays the new attributes and supports the new instruction formats; it may have a shorthand for checked type constants
- `java.lang.constant` might provide a dedicated subclass of DynamicConstantDesc to represent CheckedType constants
- JEP 457: Class-File API (Preview) may need updates to support the new attributes and instruction formats
### ImplicitCreation attribute
The `ImplicitCreation` attribute may be applied at the `ClassFile` level to a class to opt in to implicit zero instance creation.
ImplicitCreation_attribute {
u2 attribute_name_index;
u4 attribute_length;
}
Format checking fails if an `ImplicitCreation` attribute is applied to an identity class or any interface.
There is no requirement that an `<init>` method of the class matches the Java language requirements for an implicit constructor. Implicit creation in the JVM does not make use of `<init>` methods.
The _zero instance_ of a concrete value class that has an `ImplicitCreation` attribute is a class instance with all instance fields set to their default values. The JVM may freely "create" this instance whenever necessary.
### CheckedType constants
A "`CheckedType` constant" is defined as a `CONSTANT_Dynamic` constant whose bootstrap method belongs to the class 'java.lang.runtime.CheckedTypeBootstraps` and whose `NameAndType` must have a the descriptor `Ljava/lang/reflect/CheckedType;`. (In the future, either the bootstrap restriction will be dropped, or a dedicated constant form will be defined.)
(TODO: do we need to impose class loader constraints on these types?)
Checked types may be represented internally in whatever way is convenient; for now, a checked type constant represents one of:
- A reference class type (not a primitive type)
- A null-restricted value class type, where the value class has an `ImplicitCreation` attribute
As for any `Dynamic` constant, an `ldc` may refer to a `CheckedType` constant.
### Casts
The `checkcast` instruction may opt to refer to a `CheckedType` constant instead of a `Class` constant.
For verification, the output type of the instruction is the same as its input type, no matter what kind of `CheckedType` constant is denoted. (A traditional cast using a `Class` constant must be used to communicate type assertions to the verifier.)
At run time, the `CheckedType` constant is first resolved (even if a `null` is on the stack). Then the checked type is enforced, possibly failing with a `ClassCastException` or a `NullPointerException`.
(The `instanceof` instruction may _not_ refer to a `CheckedType` constant, since `Class` constants already produce `false` for null inputs.)
### Arrays
The `anewarray` instruction may opt to refer to a `CheckedType` constant instead of a `Class` constant. The checked type denotes the array's component type. The array components are initialized to the component type's default value; if the component type is a null-restricted type, the default value is the zero instance of the named class.
Array stores (e.g., via `aastore`) check the component type, as usual, and throw `ArrayStoreException` if the input does not satisfy the checked type.
There is no JVM type to represent `Foo![]` (at least for now); this erases to the type `Foo[]`.
There is no change to the `multianewarray` instruction. A multi-dimensional array with null-restricted elements must be constructed manually.
Invocations of the `clone` method of an array type should create a copy that uses the same `CheckedType` as the original.
### Fields
The `FieldCheckedType` attribute may be applied to a `field_info` structure to indicate a dynamically-checked type of the field.
FieldCheckedType_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 checkedtype_index;
}
The `checkedtype_index` must refer to a `CheckedType` constant.
If a checked type is present, the initial value of the field, as set by preparation, is the checked type's default value. For a null-restricted type, this is the zero instance of the named class.
Field writes (e.g., via `putfield` or `putstatic`) dynamically check the checked type and throw `FieldStoreException` if the input does not satisfy the checked type.
The checked type of a field is distinct from its descriptor type, which is enforced by linkage rather than dynamic checks. The descriptor type and checked type need not be related.
### Atomicity
A null-restricted field or array storing value objects must typically ensure that the data will be updated atomically.
A value class may optionally implement the `LooselyConsistentValue` interface (either directly or indirectly), and if so, the JVM is free to handle null-restricted fields and arrays of that type in a way that does not guarantee atomic updates.
### Class loading
Class loading fails for a class with an `ImplicitCreation` attribute if any of:
- The superclass is not `Object` and does not have an `ImplicitCreation` attribute
- The zero instance of the class contains itself (via a circularity in the `FieldCheckedType` attributes of instance fields)
When preview features are enabled, the following non-preview classes are treated as if they had `ImplicitCreation` set:
- java.lang.Number
- java.lang.Record
- All 8 wrapper classes
- java.util.Optional
### Initialization
The `anewarray` instruction requires initialization of the component type's class if the component type is a null-restricted type.
When initializing a class, any other class that appears as a null-restricted checked type of one of the first class's fields must recursively be initialized.
### Runtime checking
Casts, array writes, and field writes may perform null checks and class checks, as described above. These are internal JVM operations—no Java code (such as a 'CheckedType.cast' invocation) is executed.
In C2, the type system is able to track these properties (including nullness), and checks that can be statically proven to be redundant are skipped at run time.
### Object encodings
In *this release* of HotSpot, value objects stored in null-restricted fields and arrays encoded as follows. (These details are subject to change in future releases.)
- If the object's fields can be stored in an atomic word size (e.g., 64 bits), null-restricted fields and arrays encode the object in a bit vector of that size, and reads and writes are performed atomically.
- Otherwise, if the value class implements `LooselyConsistentValue` (directly or indirectly), and the field is not `volatile`, and the number/size of fields is within some threshold, null-restricted fields and arrays encode the object as a sequence of field values, each of which is read/written independently. Some extra padding may be inserted in arrays to achieve good alignment.
- Otherwise, the object is encoded as a regular heap object.
Null-restricted arrays are initialized eagerly. If the array is flattened, memory is set to zeroes, and those zero bits are interpreted as the zero instance of the class. If the array is not flattened, a zero instance of the class is located or allocated, and each component is set to a pointer to that instance.
Null-restricted fields are always initialized with zeroes. If the field is not flattened, then this is a lazy initialization strategy: the bits encode a `null` pointer, which is detected by the first field read (`getfield`, `getstatic`) and replaced at that point with an appropriate pointer to a zero instance.
### Signature attributes
The syntax of the `Signature` attribute is enhanced to denote null-restricted Java language types by appending a `!` symbol to a class type:
ClassTypeSignature:
L [PackageSpecifier] SimpleClassTypeSignature {ClassTypeSignatureSuffix} [ ! ] ;
Note that the ! appears _after_ any type arguments rather than _before_ them, to avoid disrupting the structure of `SimpleClassTypeSignature` and `ClassTypeSignatureSuffix`. (A '!' would not make sense on an outer class type that qualifies an inner class type.)
### Other JVM tools and APIs
- `java.lang.invoke` may need to implement the new array and field storage checks
- `javap` displays the new attributes and supports the new instruction formats; it may have a shorthand for checked type constants
- `java.lang.constant` might provide a dedicated subclass of DynamicConstantDesc to represent CheckedType constants
- JEP 457: Class-File API (Preview) may need updates to support the new attributes and instruction formats