Make new Object() backward compatible

Remi Forax forax at univ-mlv.fr
Sun May 9 14:15:17 UTC 2021


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


More information about the valhalla-spec-observers mailing list