> On Dec 1, 2021, at 8:48 AM, Dan Heidinga <heidi...@redhat.com> wrote: > >> class file representation & interpretation >> >> A value class is declared in a class file using the ACC_VALUE modifier >> (0x0100). At class load time, the class is considered to implement the >> interface ValueObject; an error occurs if a value class is not final, has a >> non-final instance field, or implements—directly or >> indirectly—IdentityObject. > > I'll reiterate my earlier pleas to have javac explicitly make them > implement ValueObject. The VM can then check that they have both the > bit and the interface.
So we went down the path of "maybe there's no need for a flag at all" in today's meeting, and it might be worth more consideration, but I convinced myself that the ACC_VALUE flag serves a useful purpose for validation and clarifying intent that can't be reproduced by a "directly/indirectly extends ValueObject" test. As you suggest, though, we could mandate that ACC_VALUE implies 'implements ValueObject'. Some reasons not to require this: - 'implements ValueObject' may be redundant if an ancestor implements ValueObject; but leaving it off risks a separate compilation error (e.g., ancestor used to implement ValueObject, doesn't anymore). So I think the proper compilation strategy would be to always implement it directly, even redundantly. There's an opportunity for a subtle compiler bug. - It's extra ceremony in the class file. <shrug> - Inferring is consistent with what we do for at least some identity classes. Inferring everywhere is, in some ways, simpler.* (*Tangent about the idea of inferring IdentityObject in old versions, but requiring IdentityObject in new versions: the trouble with gating off less-preferred behavior in old versions is that it's still there and still must be supported. JVMs end up with two strategies instead of one. A (great strategy+ok strategy) combination is arguably *worse* than just (ok strategy) everywhere.) > It's a simpler model if the interface is > always there for values as the VM won't have to track whether it was > injected for a value class or explicitly declared. Why does that > matter? For two reasons: JVMTI will need to be consistent in the > classfile bytes it returns and not included the interface if it was > injected (less tracking), and given earlier conversations about > whether to "hide" the injected interface from Class::getInterfaces, > always having it for values removes one more sharp edge. The plan of record is to make no distinction between inferred and explicit superinterfaces in reflection. Is that not acceptable for JVMTI? If there's no need for a distinction, does that address your concern about inferred supers?