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 [1]. 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?

[1] 
http://cr.openjdk.java.net/~dlsmith/lw2/lw2-20190628/specs/init-methods-jvms.html

Reply via email to