<init> and factories
brian.goetz at oracle.com
Thu Oct 17 19:20:10 UTC 2019
I think the choice to keep the reserved space is a good one.
For the <init> vs <new> distinction, it makes me want to ask: what's a
factory? Obviously, inline classes have constrained-form constructors
that are translated to factory methods, but is this the end of the
factory story, or the beginning?
As has been discussed, javac could well generate _both_ a <init> method
and a factory, where the latter is derived from the former via
new/dup/init. Whether this is desirable depends on what we get for this.
But, the question that this plan leaves me wondering is whether there
should be a notion of a factory in the language (such a concept would
warrant a novel translation strategy, if for no other reason than not
being lossy.) Currently, we use the word "factory" quite loosely
(basically, any this-class-returning static method), and there's no type
checking that, for example, prevents a factory from returning null.
So I think much of the value of having a factory concept in the VM is
coupled to whether we have a factory concept in the language.
(If we asked the personification of records, he/she would definitely
want factory methods, because then we could be justified in making
constructors private and instead exposing a factory, as this would
actually have linguistic meaning.)
On 10/17/2019 2:22 PM, Dan Smith wrote:
> The plan of record for compiling the constructors of inline classes is
> to generate static methods named "<init>" with an appropriate return
> type, and invoke them with 'invokestatic'.
> This requires relaxing the existing restrictions on method names and
> references. Historically, the special names "<init>" and "<clinit>"
> have been reserved for special-purpose JVM rules (for example,
> 'invokespecial' is treated like a distinct instruction if it invokes a
> method named '<init>'); for convenience, we've also prohibited all
> other method names that include the characters '<' or '>' (JVMS 4.2.2).
> Equivalently, we might say that, within the space of method names,
> we've carved out a reserved space for special purposes: any names that
> include '<' or '>'.
> A few months ago, I put together a tentative specification that
> effectively cedes a chunk of the reserved space for general usage .
> The names "<init>" and "<clinit>" are no longer reserved, *unless*
> they're paired with descriptors of a certain form ("(.*)V" and "()V",
> respectively). Pulling on the thread, we could even wonder whether the
> JVM should have a reserved space at all—why can't I name my method
> "bob>" or "<janet>", for example?
> In retrospect, I'm not sure this direction is such a good idea. There
> is value in having well-known names that instantly indicate important
> properties, without having more complex tests. (Complex tests are
> likely to be a source of bugs and security exploits.) Since the JVM
> ecosystem is already accustomed to the existence of a reserved space
> for special method names, we can keep that space for free, while it's
> potentially costly to give it up.
> So here's a alternative design:
> - "<init>" continues to indicate instance initialization methods;
> "<clinit>" continues to indicate class initialization methods
> - A new reserved name, "<new>", say, can be used to declare factories
> - To avoid misleading declarations, methods named "<new>" must be
> static and have a return type that matches their declaring class; only
> 'invokestatic' instructions can reference them
> - The rest of the "<.*>" space of names (plus ".*<.*" and ".*>.*") is
> held in reserve, available for special purposes as we discover them
> The Java compiler would only use "<new>" methods for inline class
> construction, for now; perhaps in the future we'll find other use
> cases that make sense (like surfacing some sort of factory mechanism).
> Does this seem promising? Any particular reason it's better to
> overload "<init>" than just come up with a new special name?
More information about the valhalla-spec-observers