The issues can be seen after compiling this Java source code:
import jdk.internal.vm.annotation.NullRestricted;
import jdk.internal.vm.annotation.Strict;
public class NRTest {
static value class Value {
int i = 0;
}
@Strict
@NullRestricted
Value v = new Value();
public static void main(String[] args) {
var t = new NRTest();
}
}
When disassembling the produced class file, the information related to the field v is:
NRTest$Value v;
descriptor: LNRTest$Value;
flags: (0x0800) ACC_STRICT_INIT
RuntimeVisibleAnnotations:
0: #18()
jdk.internal.vm.annotation.NullRestricted
RuntimeInvisibleAnnotations:
0: #20()
jdk.internal.vm.annotation.Strict
Javac correctly sets the ACC_STRICT_INIT flag in the field's access flags.
However, javac also puts jdk.internal.vm.annotation.Strict in the set of runtime annotations of the field. This is redundant with the ACC_STRICT_INIT flag, and it is not consistent with the definition of the Strict annotation which is declared as having a SOURCE policy retention:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Strict {
}
Another observation is that javac adds the type of field v to the LoadableDescriptors attribute:
LoadableDescriptors:
LNRTest$Value;
The presence of the field's type in the LoadableDescriptors attribute is not an error, but it is useless and in fact triggers more work in the JVM. Types of non-static null-restricted (an by consequence strict) fields are automatically loaded by the JVM without consulting the LoadableDescriptors attribute. The presence of this type in the attribute will trigger another attempt to load the type at class link time, which is a waste of time because the type is already present in the system dictionary at this time.
Note that non-static null-restricted fields are the only ones currently having their type automatically loaded by the JVM, for all other types from static fields and method arguments, the presence in the LoadableDescriptors attribute is required to guarantee layout and calling convention optimizations.
import jdk.internal.vm.annotation.NullRestricted;
import jdk.internal.vm.annotation.Strict;
public class NRTest {
static value class Value {
int i = 0;
}
@Strict
@NullRestricted
Value v = new Value();
public static void main(String[] args) {
var t = new NRTest();
}
}
When disassembling the produced class file, the information related to the field v is:
NRTest$Value v;
descriptor: LNRTest$Value;
flags: (0x0800) ACC_STRICT_INIT
RuntimeVisibleAnnotations:
0: #18()
jdk.internal.vm.annotation.NullRestricted
RuntimeInvisibleAnnotations:
0: #20()
jdk.internal.vm.annotation.Strict
Javac correctly sets the ACC_STRICT_INIT flag in the field's access flags.
However, javac also puts jdk.internal.vm.annotation.Strict in the set of runtime annotations of the field. This is redundant with the ACC_STRICT_INIT flag, and it is not consistent with the definition of the Strict annotation which is declared as having a SOURCE policy retention:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface Strict {
}
Another observation is that javac adds the type of field v to the LoadableDescriptors attribute:
LoadableDescriptors:
LNRTest$Value;
The presence of the field's type in the LoadableDescriptors attribute is not an error, but it is useless and in fact triggers more work in the JVM. Types of non-static null-restricted (an by consequence strict) fields are automatically loaded by the JVM without consulting the LoadableDescriptors attribute. The presence of this type in the attribute will trigger another attempt to load the type at class link time, which is a waste of time because the type is already present in the system dictionary at this time.
Note that non-static null-restricted fields are the only ones currently having their type automatically loaded by the JVM, for all other types from static fields and method arguments, the presence in the LoadableDescriptors attribute is required to guarantee layout and calling convention optimizations.