The Record Attribute - What does it mean to be a record at runtime?
forax at univ-mlv.fr
forax at univ-mlv.fr
Thu Nov 12 21:41:33 UTC 2020
----- Mail original -----
> De: "Maurizio Cimadamore" <maurizio.cimadamore at oracle.com>
> À: "daniel smith" <daniel.smith at oracle.com>, "Chris Hegarty" <chris.hegarty at oracle.com>
> Cc: "Remi Forax" <forax at univ-mlv.fr>, "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> Envoyé: Jeudi 12 Novembre 2020 22:15:05
> Objet: Re: The Record Attribute - What does it mean to be a record at runtime?
> I think the point Chris is raising is a bit more subtle.
>
> The VM has a notion of classes in which final fields are trusted - when
> that happens, the value of final fields are constant folded by the JIT
> (yayy!).
>
> There is a problem though: in practice, final fields can be mutated e.g.
> by reflection, or via 292 (var handles) or via Unsafe.
>
> For this reason, when we trust final fields in class C, we typically do
> other changes to prevent fields in class C from being exposed (e.g. via
> reflection), so as to decrease the potential that JIT optimization would
> be invalidated, either accidentally or maliciously.
>
> 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.
>
> * 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).
>
> * 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).
>
> So, the way I see it, is that there are few ways out of this conundrum:
>
> 1) Back away from final field optimization for records; we could in fact
> get rid of all the asymmetries described above by simply _not_ trusting
> record fields - at which point VM support would become again very minimal.
>
> 2) Enforce a definition of "is a record" which makes sense - and then
> enable extra optimizations on top. Since we need to be able to specific
> reflection restriction (Field::set) I think the only defensible
> definition for what constitutes a record is to delegate to
> Class::isRecord. This doesn't mean that the JVM will have to start
> taking into account the JLS definition of a record at verification time
> - it simply means that the final field optimization, instead of being
> gated on the mere _presence_ of the record attribute, it would be
> governed by a more complex definition which matches the behavior of
> Class::isRecord. Note that this is all below the JVMS surface.
>
> What Chris is saying is (I think) that the current implementation is
> caught in some inconsistent place between (1) and (2) - a place where,
> on one hand, we claim VM neutrality w.r.t. the record definition
> contained in the JLS but where, at the same time, we apply extra
> optimizations to speed up access to record fields.
For me, you are focusing on the wrong side of the time line,
trusted final fields should be the new normal and plain old classes are the ones that are weird because they have a *weak* final fields semantics.
So instead of saying that records, hidden classes, anonymous classes (and soon primitive object classes) are special, the VM should say that plain old classes are the outlier.
With that, the JLS definition of a record doesn't need to leak into the JVMS.
>
> Maurizio
Rémi
>
> On 11/11/2020 02:39, Dan Smith wrote:
>>> On Nov 10, 2020, at 1:51 PM, Chris Hegarty <chris.hegarty at oracle.com> wrote:
>>>
>>> My issue is with how the VM determines whether a field is trusted or not. The VM
>>> trusts fields in (among other types) “record” classes. So what is a record
>>> class to the VM? (that is the question that I am trying to resolve) - the
>>> answer is not in the JVMS ( which is fine ).
>> Suggestion: the VM shouldn't bother to provide any definition for "record
>> class". That's up to Java language compilers and reflection (which should be in
>> agreement).
>>
>> Instead, can't we say the VM trusts fields in classes that have a Record
>> attribute? Who cares whether those classes are "real" records or not? (I may be
>> missing something because I don't fully understand the concept of "trusted
>> final field", but it seems to me like HotSpot has a lot of freedom to decide to
>> trust or not trust whatever fields it wants.)
More information about the amber-spec-experts
mailing list