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

Class::isRecord should check that the current class is final and not abstract

    XMLWordPrintable

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P3
    • Resolution: Approved
    • Fix Version/s: 16
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Compatibility Risk:
      low
    • Compatibility Risk Description:
      Hide
      Class::isRecord previewed in Java 14 and again in Java 15. It is now standard in Java 16 - its first non-preview release. The Hotspot VM will not load non-final classes that contain a Record Attribute in 14/15. Given this, it seems like a low compatibility risk to make this change in Java 16.
      Show
      Class::isRecord previewed in Java 14 and again in Java 15. It is now standard in Java 16 - its first non-preview release. The Hotspot VM will not load non-final classes that contain a Record Attribute in 14/15. Given this, it seems like a low compatibility risk to make this change in Java 16.
    • Interface Kind:
      Java API
    • Scope:
      SE

      Description

      Summary

      Update Class::isRecord to only return true for classes that are final.

      Problem

      The removal of non-specified JVM checks on classes with a Record Attribute (see JDK-8255342), has resulted in more types of loadable classes that may contain a Record Attribute. Since these checks are not performed by the JVM anymore, Class::isRecord, and by extension Class::getRecordComponents, may return true or component values, respectively, for classes that are not well-formed record classes (as per the JLS), .e.g. non-final or abstract classes, that contain a record Attribute.

      Solution

      Core Reflection, Class::isRecord, already asserts checks that the JVM does not, e.g. that the direct superclass is java.lang.Record.

      Some points from the Java Language Specification for record classes:

      1. It is a compile-time error if a record declaration has the modifier abstract.
      2. A record declaration is implicitly final.
      3. The direct superclass type of a record class is Record.

      Class::isRecord already ensures no.3. This issue proposes to add explicit checks in Core Reflection to ensure #1 and #2, since the JVM now allows such classes that contain a Record Attribute to be loaded.

      Note: asserting that a class is final is sufficient, as it implies that the class it non-abstract - an assertion guaranteed by the JVM.

      Specification

      java.lang.Class:

         /**
          * Returns {@code true} if and only if this class is a record class.
          *
          * <p> The {@linkplain #getSuperclass() direct superclass} of a record
      -   * class is {@code java.lang.Record}. A record class has (possibly zero)
      -   * record components, that is, {@link #getRecordComponents()} returns a
      -   * non-null value.
      +   * class is {@code java.lang.Record}. A record class is {@linkplain
      +   * Modifier#FINAL final}. A record class has (possibly zero) record
      +   * components; {@link #getRecordComponents()} returns a non-null but
      +   * possibly empty value for a record.
          *
          * <p> Note that class {@link Record} is not a record type and thus invoking
          * this method on class {@code Record} returns {@code false}.
          *
          * @return true if and only if this class is a record class, otherwise false
          * @jls 8.10 Record Types
          * @since 16
          */
         public boolean isRecord() { ... }

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              chegar Chris Hegarty
              Reporter:
              vromero Vicente Arturo Romero Zaldivar
              Reviewed By:
              Mandy Chung
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: