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

Dan Smith daniel.smith at oracle.com
Fri Nov 13 04:34:51 UTC 2020


> On Nov 12, 2020, at 2:15 PM, Maurizio Cimadamore <Maurizio.Cimadamore at oracle.com> wrote:
> 
> I think the current state of affair for records has at least 3 issues:
> 
> * The paths which controls which fields are trusted by VM and which fields are exposed via reflection/292/unsafe do not align 100%. For instance, Unsafe refuses to give up field offset based on the stricter Class::isRecord definition, thus creating a safety gap.

Agree that's a problem. All the components involved in trusted fields need to be in agreement about which final fields are trusted.

> * In an attempt to prevent changes to records fields via reflection, the specification of Field::set was updated to say that if the field holder is a record, the field update will fail. This is good, if it weren't that the javadoc has to define what it means for a field holder to be a record; and the way that's done is by referring to Class::isRecord, which is not what the implementation does (the implementation uses the broader "isRecord" definition based on the presence/absence of the record attribute - the same used by the VM).

Agree the spec and implementation should be consistent. That doesn't necessarily mean they need to use Class.isRecord as their test. It could just as easily be checking for the attribute, or testing that the class extends java.lang.Record, or maybe something else. There are multiple places to draw the line.

But all I'm saying is that there are multiple possibilities. While I think having a super-simple test might be attractive, I'm not in a position to weigh that against other concerns.

> * All clients have now a way to enable the (fragile) final field optimization: generate a class, then attach a record attribute to it (e.g. with ASM). The VM will trust all fields in that class no matter what. I think this is probably not what was originally intended by the changes in JDK-8247444. In other words, we now have a mechanism which is kind of like the internal @ForceInline annotation - not as handy as an annotation perhaps, but much more public (because, any classfile can be augmented to contain an extra, maybe empty, record attribute).

Right. If there's a concern that *too many* classes will have trusted fields, then drawing the line more narrowly is useful. It's possible—I'm not sure—that saying "all subclasses of java.lang.Record" would raise fewer concerns here than "all classes with a Record attribute". Not because it's necessarily harder to physically put in the class file, but because extending a class is a strong signal that you intend to adopt any special contracts/treatment associated with that class.



More information about the amber-spec-experts mailing list