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

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

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • 16
    • core-libs
    • None
    • low
    • 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.
    • Java API
    • SE

      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() { ... }

            chegar Chris Hegarty
            vromero Vicente Arturo Romero Zaldivar
            Mandy Chung (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: