I think there is a way to avoid all the issues we have with new Object().

The problem:
  We want to inject the interface IdentityObject on all classes that are 
neither a "no field" abstract class nor a primtive class.
  But java.lang.Object acts as a "no field" abstract class but it's not an 
abstract class.

Clearly, there are two java.lang.Object, the one which is the root of all 
classes (the "no field" abstract one) and the one which can be instantiated 
that should implements IdentityObject.

The logical conclusion is that java.lang.Object is a parametric class with a 
parameter saying if it should implement IdentityObject or not.

The "raw" version does not implement IdentityObject, that the one used when a 
class extends Object.
The parameterized version implements IdentityObject and is the one used by new 
Object()

So the classfile Object.class should contain a SpecializationAnchor, and being 
a "no field" class or not is an attribute that references the Anchor.

To maintain backward compatibility, when the VM sees the opcode NEW 
java/lang/Object, it adds a new constant pool entry of kind 
SpecializationLinkage that reference java/lang/Object with a constant asking 
for version that implements IdentityObject and rewrite NEW java/lang/Object to 
NEW Linkage(java/lang/Object).

Obviously, there is the bootstraping issue with the code in java.lang.invoke 
making the BSM working not be initialized at the time java.lang.Object need to 
be available, so the VM has to inject the binding early as if it was resolved 
by the BSM but i think it's workable.

When the VM starts, if there are some new Object() executedbefore the code of 
java.lang.invoke is ready, those code can be rewritten to use a special class 
defined in the JDK for that like
  package jdk.internal.whatever;
  class LockObject { }

Even if it's not strictly necessary, javac can be changed to emit the 
Linkage(java/lang/Object) each time a new Object() is needed to the rewriting 
by the VM described above need to be done only for the classfiles that are 
using previous versions.

I believe this change is fully source and binary compatible and nice property 
is that 
  new Object().getClass() == Object.class
is still true.

RĂ©mi

Reply via email to