Abstract class with fields implementing ValueObject
Dan Smith
daniel.smith at oracle.com
Thu Feb 24 23:58:35 UTC 2022
TLDR: I'm convinced, let's revise our approach so that the JVM never infers interfaces for abstract classes.
On Feb 24, 2022, at 8:57 AM, Dan Heidinga <heidinga at redhat.com<mailto:heidinga at redhat.com>> wrote:
Whether
they can be instantiated is a decision better left to other parts of
the spec (in this case, I believe verification will succeed and
resolution of the `super()` <init> call will fail).
Right, my mistake. Verifier doesn't care what methods are declared in the superclass, but resolution of the invokespecial will fail.
(3) no ACC_PERMITS_VALUE, <init> declaration
The JVM infers that this class implements IdentityObject, if it doesn't already. If it also implements ValueObject, an error occurs at class load time.
I think this should be driven purely by the presence of the
ACC_PERMITS_VALUE flag and the VM shouldn't be looking at the <init>
methods.
Sounds like the consensus, agreed.
The JVM shouldn't infer either IdentityObject or ValueObject
for this abstract class - any inference decision should be delayed to
the subclasses that extend this abstract class.
My initial reaction was that, no, we really do want IdentityObject here, because it's useful to be able to assign an abstract class type to IdentityObject.
But: for new classes, the compiler will have an opportunity to be explicit. It's mostly a question of how we handle legacy classes. And there, it would actually be bad to infer IdentityObject, when in most cases the class will get permits_value when it is recompiled. Probably best to avoid a scenario like:
- Compile against legacy API, assign library.AbstractBanana to IdentityObject in your code
- Upgrade to newer version of the API, assignment from library.AbstractBanana to IdentityObject is an error
So, okay, let's say we limit JVM inference to concrete classes. And javac will infer/generate 'implements IdentityObject' if it decides an abstract class can't be permits_value.
What about separate compilation? javac's behavior might be something like: 1) look for fields, 'synchronized', etc. in the class declaration, and if any are present, add 'implements IdentityObject' (if it's not already there); 2) if the superclass is permits_value and this class doesn't extend IdentityObject (directly or indirectly), set permits_value. (1) is a local decision, while (2) depends on multiple classes, so can be disrupted by separate compilation. But, thinking through the scenarios here... I'm pretty comfortable saying that an abstract class that is neither permits_value nor a subclass of IdentityObject is in an unstable state, and, like the legacy case, it's probably better if programmers *don't* write code assuming they can assign to IdentityObject.
More information about the valhalla-spec-observers
mailing list