JDK-8233595 : JVM reflection support for records
  • Type: CSR
  • Component: hotspot
  • Sub-Component: runtime
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 14
  • Submitted: 2019-11-05
  • Updated: 2020-11-10
  • Resolved: 2020-05-20
Related Reports
CSR :  
Relates :  
Relates :  
Relates :  
Description
Summary
-------

Introduce a Record attribute in the `class` file format, so that the JVM can provide reflection support for components of record types.


Problem
-------

Record classes ([JEP 359][1]) are a preview feature of Java SE 14. The JVM will need to support reflecting over records and their components.

Solution
--------

A Record attribute will be defined in the `ClassFile` format, containing information about the record class and its components. The JVM will use the attribute's contents to satisfy reflection requests when the Java API `Class::getRecordComponents` is used.

The format of the Record attribute is checked by the JVM even if no reflection is performed.  The checking is done at class load time, and is similar to format checking of attributes such as Exceptions and InnerClasses.  For example, the JVM checks that the attribute's constant pool indexes are valid and that each component's attributes occur only once.  This contrasts with other attributes, such as MethodParameters, that are not examined unless reflection is performed.

Note that the Record attribute could potentially be useful in other ways, for example, in determining if a class is a record.

The specifications for class redefinition and retransformation, in the JVM TI specification are enhanced to disallow any modification of the `Record` attribute. 

Specification
-------------

Java Virtual Machine Spec changes for the Record attribute are attached.

  [1]: https://bugs.openjdk.java.net/browse/JDK-8222777
  [2]: http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jvms.html

The JVM TI specification changes are as follows:

    @@ -7633,8 +7633,8 @@
             (unless explicitly prohibited).
             The retransformation must not add, remove or rename fields or methods, change the
             signatures of methods, change modifiers, or change inheritance.
    -        The retransformation must not change the <code>NestHost</code> or
    -        <code>NestMembers</code> attributes.
    +        The retransformation must not change the <code>NestHost</code>,
    +        <code>NestMembers</code>, or <code>Record</code> attributes.
             These restrictions may be lifted in future versions.
             See the error return description below for information on error codes
             returned if an unsupported retransformation is attempted.

    @@ -7786,11 +7786,11 @@
             (unless explicitly prohibited).
             The redefinition must not add, remove or rename fields or methods, change the
             signatures of methods, change modifiers, or change inheritance.
    -        The retransformation must not change the <code>NestHost</code> or
    -        <code>NestMembers</code> attributes.
    +        The redefinition must not change the <code>NestHost</code>,
    +        <code>NestMembers</code>, or <code>Record</code> attributes.
             These restrictions may be lifted in future versions.
    -	See the error return description below for information on error codes
    -	returned if an unsupported redefinition is attempted.
    +        See the error return description below for information on error codes
    +        returned if an unsupported redefinition is attempted.
             The class file bytes are not verified or installed until they have passed
             through the chain of <eventlink id="ClassFileLoadHook"/> events, thus the
             returned error code reflects the result of the transformations applied


Comments
Thank you [~dholmes] for adding the JVM TI changes; moving amended request back to Approved.
20-05-2020

It has been discovered that the JVM TI specification changes in regards to Records have not been covered by a CSR request. As there was no specific issue pertaining to the JVM TI changes Joe suggested it best to update this CSR request to include the JVM TI spec changes (which are very small and easily incorporated). I will undertake that addition.
20-05-2020

Moving to Approved.
26-11-2019

An update that incorporates some feedback from elsewhere is attached. No changes of any substance���specifically, the update consists of: - Renaming `component_info` to `record_component_info`, for clarity - Rephrasing the `Synthetic` text to refer to "implicitly-declared members" rather than "mandated members" - Rephrasing "record class" -> "record type", consistent with JLS - Deleting a resolved design discussion (4.7.30), and framing another (4.7.20) as "maybe we'll want to do this when we finalize"
25-11-2019

The JVM spec is not in the business of deciding how non-critical attributes will be interpreted. That's up to the reflection API and other tools. (For example, the Signature attribute spec does not describe precisely under which conditions the attribute will be considered valid, what happens if the signature and descriptor disagree, etc.) So: - No, the JVM spec is not the place to define "record-ness". - Clients of the class file must determine for themselves what happens if a Record attribute is present on a class that is not a record. I'll note that while, ideally, the reflection javadoc and javac documentation, among other things, could say something about this, in practice I don't think we've ever been that precise. (See, for example, the specification of 'Class.getGenericSuperclass'. Lots of unspecified behavior here involving malformed class files.)
25-11-2019

Should the JVM spec say something about how record-ness is determined? What happens if a Record attribute is present on a class that is not a record? Marking the request as pended; please re-finalize when updated.
22-11-2019

I hesitate to get into details about how reflection chooses to interpret JVM attributes. The proper place to document that behavior is in the API itself. Instead, how about we be *less* assertive? "The `Record` attribute is a variable-length attribute in the `attributes` table of a `ClassFile` structure. The `Record` attribute records information about the components of a record class (JLS 8.10)." (I've attached this change. There's another bundle, 4 minutes older, that didn't include the change. Please disregard. JBS doesn't let me delete attachments.)
20-11-2019

"A class with the Record attribute is a record class, and has a specified list of components." I was expecting to see a mention of java.lang.Record in conjunction with determining record-ness of a type. Moving to Provisional.
15-11-2019

The document makes a stale reference to an old JLS edition: 4.7.9 The Signature Attribute The Signature attribute is a fixed-length attribute in the attributes table of a ClassFile, field_info, or method_info, or component_info structure (4.1, 4.5, 4.6, 4.7.30). A Signature attribute records a signature (4.7.9.1) for a class, interface, constructor, method, or field, or record component whose declaration in the Java programming language uses type variables or parameterized types. See *The Java Language Specification, Java SE 12 Edition* for details about these constructs. In 4.7.20 The RuntimeVisibleTypeAnnotations Attribute, presumably the text It may be appropriate to introduce a new target_type value for record components rather than re-using 0x13. should be in a commentary box. Syntactically, shouldn't all of 4.7.30 The Record Attribute be in bold? Is there a general list of "Here are preview features for the JVMS release" that should also be updated as part of this CSR? Moving to Provisional (rather than Approved).
08-11-2019