Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8247517

Final fields in records are not reflectively modifiable

    XMLWordPrintable

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P3
    • Resolution: Approved
    • Fix Version/s: 15
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Compatibility Risk:
      minimal
    • Interface Kind:
      Java API
    • Scope:
      SE

      Description

      Summary

      Make final fields in records not reflectively modifiable such that final fields in records are trusted for JIT optimization.

      Problem

      Final fields are not trusted because they are not truly final and can be modified via reflection. For new features, it's desirable to make final fields truly final where possible.

      Solution

      Make final fields in records not modifiable via reflection. A JIT compiler can trust these final fields truly final.

      Field::setAccessible(true) will succeed to allow existing frameworks to have read access to fields. If it's a final field in a record class, it's not modifiable. Field::set will throw IllegalAccessException because it is not modifiable, i.e. no write access.

      Specification

      java.lang.reflect.AccessibleObject::setAccessible specifies that final fields in records are not modifiable. As specified in Field::set, static final fields of any class or interface cannot be modified. This spec change includes the static final fields in the list of non-modifiable fields for completeness.

      --- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
      +++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
      @@ -177,10 +177,16 @@
            * to the caller's module. </p>
            *
            * <p> This method cannot be used to enable {@linkplain Field#set <em>write</em>}
      -     * access to a final field declared in a {@linkplain Class#isHidden() hidden class},
      -     * since such fields are not modifiable.  The {@code accessible} flag when
      -     * {@code true} suppresses Java language access control checks to only
      -     * enable {@linkplain Field#get <em>read</em>} access to such fields.
      +     * access to a <em>non-modifiable</em> final field.  The following fields
      +     * are non-modifiable:
      +     * <ul>
      +     * <li>static final fields declared in any class or interface</li>
      +     * <li>final fields declared in a {@linkplain Class#isHidden() hidden class}</li>
      +     * <li>final fields declared in a {@linkplain Class#isRecord() record}</li>
      +     * </ul>
      +     * <p> The {@code accessible} flag when {@code true} suppresses Java language access
      +     * control checks to only enable {@linkplain Field#get <em>read</em>} access to
      +     * these non-modifiable final fields.
            *

      java.lang.reflect.Field::set is updated as follows:

            * <p>If the underlying field is final, this {@code Field} object has
            * <em>write</em> access if and only if the following conditions are met:
            * <ul>
            * <li>{@link #setAccessible(boolean) setAccessible(true)} has succeeded for
            *     this {@code Field} object;</li>
            * <li>the field is non-static; and</li>
            * <li>the field's declaring class is not a {@linkplain Class#isHidden()
      -     *     hidden class}.</li>
      +     *     hidden class}; and</li>
      +     * <li>the field's declaring class is not a {@linkplain Class#isRecord()
      +     *     record class}.</li>

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              mchung Mandy Chung
              Reporter:
              mchung Mandy Chung
              Reviewed By:
              Chris Hegarty
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: