The Record Attribute - What does it mean to be a record at runtime?

Chris Hegarty chris.hegarty at
Tue Nov 10 14:23:22 UTC 2020

Thanks for your reply Remi, comments inline.

> On 5 Nov 2020, at 23:59, Remi Forax <forax at> wrote:
>> ..
>> A recent change, 8255342 [2], laxifies the JVM checking of the Record
> ...
> What a record is, is defined by the JLS but not by the JVMS (like enums),
> so the JVM should not know what a record is given that it's an artifact of the language not an artifact of the VM.


> We are also trying to enforce more unmodifiability of the final fields in the VM, Reflection, Unsafe, VarHandle, etc.

Yes. And this is a good move.

> Because of backward compatibility, we can not just make all final fields unmodifiable, because some libraries (or worst some Jakarta EE specs) relies on the fact that a final field can be changed after construction.
> So we are selectively enabling a more stronger stance on the modifiability of final field only for new constructs, VM anonymous class, VM hidden class and record class.

Yes, this is my understanding also.

> Here the VM doesn't really need to know what a record is but only that this is a new construct so the rules around final fields are stronger, stricter.
> So for me, we do not need to do more in the VM.

I agree that The Abstract JVM does not need to concern itself with the
details of a record beyond the currently specified checks for the Record
Attribute in the JVMS.

> Now, for the reflection part, the reflection is mostly the Java view of the world, it's not stricto sensu true because you can see the desugaring done by the compiler.
> The reflection knows what a record is, it has to directly inherits from java.lang.Record, be final and have a RecordComponents attribute (gently provided by the VM).
> So both isRecord and getRecordComponents should checks these properties.

Currently the core Java Reflection implementations determine whether a
field is a trusted final based on information served up by the VM. One
of the criteria that the VM uses to determine this is whether, or not,
the field's containing class is a record. The VM asserts that a class is
a record if it has a parsable Record attribute.

Core reflection, however, determines a class to be a record class if the
class is 1) a direct subclass of j.l.Record, and 2) contains a Record

One option is to just update Class::isRecord to ensure, along with the
above #1 and #2 checks, that the class is also 3) final, and
4) non-abstract. But this leaves a kind of impedance mismatch between
both the VM and the libraries, and would require Core Reflection,
MethodHandles, and VarHandles to also be updated, since their
implementation is based on the VM's trusted final determination, whereas
their specification is built atop Class::isRecord.

A better option would be to update the VM implementation to only assert
that the fields of a record-like class are trusted if that class
contains 1) a structurally sound Record attribute, 2) is a direct
subclass of j.l.Record, 3) is final, and 4) is non-abstract. This would
align Core Reflection and the VM in this respect, while the JVMS would
remain unchanged - it's an implementation detail.

The above option is actually a slight rework of the changes for 8255342.
(it is not a reversal of 8255342). The VM would still continue to parse
and structurally verify the Record attribute, but only determine the
record-ness/trusted-finalness-of-fields if the class is truly a record
class as envisaged by the JLS. This seems like a reasonable compromise
position.  ( Note: with this proposal, classes that contain a Record
Attribute, but without the other properties of what is means to be JSL
record class, would behave like normal classes - their fields would not
be trusted finals - which, again, seems reasonable.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the amber-spec-experts mailing list