XMLWordPrintable

    • Icon: Sub-task Sub-task
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • None
    • hotspot

      This task summarizes the JVM changes introduced by the Strict Field Initialization in the JVM JEP. All features are activated by the `--enable-preview` launcher option.

      Full JVMS changes to come...


      ### ACC_STRICT flag

      Any field may be marked `ACC_STRICT` (`0x0800`, used in legacy classes to indicate `strictfp` semantics for methods, but no longer meaningful) to indicate that it is strictly initialized. The flag may be used in combination with any other flag.


      ### Instance initialization states

      The initialization state of the current class instance is tracked by the verifier using one of the following:

      - *earlyLarval(unsetFields)*, where *unsetFields* is a list of strict instance fields of the current class that need to be set

      - *unrestricted*, a general-purpose symbol covering the *late larval* and *initialized* states, and also used for static methods

      - *erroneous*, indicating that initialization has failed, and preventing any exception handlers (a placeholder symbol similar, in some ways, to *afterGoto*)

      These initialization state values replace the 'flags' verification parameter. (Note that, with the exception of the list of unset fields, this is just a presentational change, expressing the combination of 'flags' and an available 'uninitializedThis'.)

      The initial state of an <init> method is *earlyLarval(...)*, with unset fields including all strict instance fields declared by the class. The initial state of any other method is *unrestricted*.

      The 'frameIsAssignable' predicate only allows transitions between identical states, or between different *earlyLarval* states where the targeted frame has a superset of unset fields.


      ### Verification of instructions

      'putfield':

      - In an *earlyLarval(...)* state, when operating on 'uninitializedThis' and referencing the current class, the outgoing initialization state removes the named field, if present, from the list of uninitialized fields (the exceptional state is unchanged)

      - For other 'putfield' instructions, reject an attempt to write to a 'strict' 'final' instance field referenced & declared in the current class

      'invokespecial':

      - When invoking an <init> method on an uninitializedThis, the incoming initialization state must be *earlyLarval(...)*. The outgoing initialization state is *unrestricted* and the exceptional initialization state is *erroneous*.

      - When invoking an <init> method on an uninitializedThis, if the method is referenced in the superclass, the list of unset fields must be empty.

      'return':

      - The 'return' instruction is only allowed in the *unrestricted* state.


      ### StackMapTable changes

      The StackMapTable is enhanced to allow the following entry, which is not a *frame*, but affects the interpretation of subsequent frames:

      assert_early_unset_fields {
          u1 frame_type = ASSERT_EARLY_UNSET_FIELDS; /* 246 */
          u2 number_of_unset_fields;
          u2 unset_fields[number_of_unset_fields];
      }

      Each unset_fields entry must reference a NameAndType constant with a field descriptor, and (probably?) that NameAndType must match a strict instance field declared in the current class, or the StackMapTable is malformed.

      The stack frames of the StackMapTable are interpreted as follows:

      - If the frame has a local variable of type 'uninitializedThis', the initialization state is *earlyLarval(...)*, with unset fields given by the closest preceding 'assert_early_unset_fields' entry (or, if none, the initial set of unset fields)

      - If the frame does not have a local variable of type 'uninitializedThis', the initialization state is *unrestricted*

      (Note that the StackMapTable does not support expressing a handler for the *erroneous* state of a failed invokespecial. This is intentional, consistent with current behavior.)


      ### Class initialization states

      The *larval* class initialization state (referred to in JVMS as "being initialized") currently keeps track of the thread performing initialization; this JEP adds information to track whether each static field has been initialized, and whether each static final field has been read.

      When the ConstantValue attribute of a field is applied, the class initialization state is updated to reflect that the field has been initialized.


      ### Static field checks

      'putstatic' (and similar reflective operations), when the resolved field's declaring class is in a *larval* state:

      - If the field is strict & static & final, the state must indicate that the field has not yet been read, or an exception (TBD) thrown

      - If the field is static & final, the state must indicate that the field has not yet been read, or a diagnostic is generated (see below)

      - If the field is static, the state is updated to indicate that the field has been initialized

      'getstatic' (and similar reflective operations), when the resolved field's declaring class is in a *larval* state::

      - If the field is strict & static, the state must indicate that the field has been initialized, or an exception (TBD) is thrown

      - If the field is static, the state must indicate that the field has been initialized, or a diagnostic is generated (see below)

      - If the field is static & final, the state is updated to indicate that the field has been read

      After a '<clinit>' method is invoked (or, if none is declared, after it *would have* been invoked), the class initialization state must indicate that every strict static field of the class has been initialized, or an exception (TBD) is thrown.


      ### Static field diagnostics

      A command-line flag (TBD) controls how diagnostics for non-strict fields generated during static field reads and writes are presented to users:

      - By default, the event is ignored

      - Under one configuration, the diagnostic is logged to the console and reported to JFR

      - Under another configuration, the diagnostic results in a fatal error

            dsimms David Simms
            dlsmith Dan Smith
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: