EG meeting, 2022-02-09 [SoV-3: constructor questions]
John Rose
john.r.rose at oracle.com
Wed Feb 9 18:32:07 UTC 2022
On 8 Feb 2022, at 19:04, Dan Smith wrote:
> "SoV-3: constructor questions": Dan asked about validation for <init>
> and <new> methods. Answer: JVM doesn't care about <init> methods in
> abstract classes, the rules about <new> methods still uncertain.
On the question of JVM validation of `<new>` methods, I’m in favor of
as few rules as possible, ideally treating `<new>` as just another name.
It’s super-power is not in its restrictions but in its
conventionality: It’s the obvious choice for constructor factory
methods. But it is not necessarily limited to that use.
Maximal limitation would be that a `<new>` method can only occur as the
translation of a value-class constructor. Any evidence in the classfile
that it was not such a translation would be grounds for failing a
validation check. We’d make as many such rules as we can think of.
Arguments against:
- Having a special method identifier in the JVMs without other
restrictions would be a new thing, and hence suspicious.
- Limiting the use of `<new>` as much as possible makes it clear, to
higher layers of the code (javac and reflection) what is going on in the
class file, as a “reflection” of the source file.
- Reflection of an irregular (non-source-conforming) `<new>` method
has to be messy. (Is it really a constructor? Or is it just a method
named `<new>`?)
Arguments in favor:
- It is a new thing in the JVM for any descriptor to be constrained to
mention the same name as is the name of the constant pool item referred
to by `ClassFile.this_class` item (JVMS 4.1). (It is suspicious.)
- A maximal limitation would break hidden classes. (They must
sometimes return a supertype from their factories, since the HC is not
always name-able in a descriptor. HCs only work because the previous
point.)
- A limitation might preclude a perhaps-desirable future translation
strategy that used `<new>` factories uniformly to translate `new` source
code expressions (identity or value objects, uniformly).
- A limitation could remove a natural translation strategy for
“canonical factory methods” in non-concrete types. This is a
hypothetical language feature for Java or some other language. (E.g.,
`new List(a,b,c)` instead of `List.of(a,b,c)`, removing the need of the
user to remember whether the word was `of` or `make` or `build` or some
other designer choice.)
- Most any limitation would preclude ad hoc use of `<new>` factories
by translation strategies of other languages, such as Scala and Clojure,
which surely have their own uses of JVM object life cycles. We want to
be friendly to non-Java languages.
Compromise positions:
- Require a `<new>` method to be `ACC_STATIC` but allow for any
purpose (i.e., any access and any descriptor).
- Require a `<new>` method to return either the class named by
`this_class` or some super type (TBD how *this* should be checked).
I would prefer the first compromise: It’s `static` but otherwise the
JVM asks no questions.
Regarding reflection, I think it would be OK to surface all of the
`<new>` methods (of whatever signature) on the `getConstructors` list,
even if they return “something odd”. Alternatively, to prevent a
sharp edge we could have a new list `Class::getFactories`, and *copy*
(not move) entries from that list onto `getConstructors` exactly when
the return type matches the enclosing class. That is a more natural
move for reflection (which operates on runtime types) than for class
file structuring (which is more static).
The reason I prefer to require `static` marking is that it would prevent
the funny name from appearing on the list of regular methods, via
reflection.
More information about the valhalla-spec-observers
mailing list