Re-interpreting 'new Object()'
daniel.smith at oracle.com
Wed Sep 2 22:08:18 UTC 2020
Followup of discussion in last week's meeting: how does 'new Object()' interact with the IdentityObject interface?
I've been able to get the story down to a few concrete changes that feel manageable.
- Add a java.lang.IdentityObject interface. The interface has no members (don't want to disrupt method resolution, etc., in any way). The javadoc, for information purposes, describes the behaviors of various Object methods.
- Add a public java.lang.SimpleIdentityObject class (I'm happy to entertain alternative names). The class has a default constructor, no members, and is 'final'. It will implicitly implement IdentityObject. The javadoc describes how it can be used as a general-purpose lock or sentinel.
- (Optionally) Add a static 'newIdentity()' method to Object, implemented as 'return new SimpleIdentityObject()'. Return type TBD. (Caution: we've never added a method to Object before. If anyone else has used that name anywhere, it will conflict. May also cause surprising reflection results from, e.g., 'getMethods'.)
- (Optionally) Make Object 'abstract'.
- The expressions 'new Object()' and 'Object::new' trigger a warning. ("Use 'Object.newIdentity' or 'new SimpleIdentityObject' instead.")
- If Object has been made abstract, 'new Object()' and 'Object::new' are exempt from the abstract class error check.
- (Optionally) In a future iteration of the language, 'new Object()' and 'Object::new' are errors (perhaps by removing the abstract class exemption).
- At runtime, the instruction 'new java/lang/Object' behaves as if it were 'new java/lang/SimpleIdentityObject'. Note that, for this reason, SimpleIdentityObject needs a well-defined, specified name. (Although we don't necessarily have to perform access control...)
- If Object has been made abstract, the instruction 'new java/lang/Object' does not perform the link-time check for an abstract class.
(The 'invokespecial Object.<init>()V' instruction is unchanged. It continues to invoke the Object constructor. Verification allows it, even though the object on the stack may be an uninitialized SimpleIdentityObject, because the 'new' instruction names 'java/lang/Object'. This may violate some assumptions about initialization method execution, but is sound because SimpleIdentityObject doesn't need to do any initialization.)
I'm not sure we'll ever be able to deprecate 'new java/lang/Object' in the JVM, but I suppose it's possible, with some disruption, for version X.0+ classes. JVMs will still need to support older class files.
Bonus discussion: Here's an alternative story, if we wanted to pursue a particular kind of factory methods in the language:
- Classes, including abstract classes and interfaces, can declare a static method named 'new', returning the class's type. (Syntax subject to bikeshedding.)
- 'new ClassName' can be used to invoke these methods as if they were constructors, without the usual hostility to abstract classes and interfaces. Invocations compile to 'invokestatic'.
- The Object class is updated to be abstract but provide one of these factories. There is no 'newIdentity' method.
- The above language changes don't apply.
- The above JVM changes are still needed. (We still have legacy 'new java/lang/Object' code.)
More information about the valhalla-spec-observers