----- Original Message -----
> From: "Dan Heidinga" <heidi...@redhat.com>
> To: "Brian Goetz" <brian.go...@oracle.com>
> Cc: "daniel smith" <daniel.sm...@oracle.com>, "valhalla-spec-experts" 
> <valhalla-spec-experts@openjdk.java.net>
> Sent: Friday, April 1, 2022 3:50:20 PM
> Subject: Re: Object as a concrete class

> On Fri, Apr 1, 2022 at 9:29 AM Brian Goetz <brian.go...@oracle.com> wrote:
>>
>>
>> > assert new Object().hasIdentity();
>> > assert !new Point().hasIdentity();
>> >
>> > But the 'hasIdentity' method can contain arbitrary logic, and doesn't
>> > necessarily need to correlate with 'getClass().isIdentityClass()'.
>>
>> More precisely, we were being held hostage to the nature of interfaces;
>> by using `implements IdentityObject` as our measure of id-ness, we
>> forced legacy Object instances to be instances of some other class, so
>> that Object didn't need to implement the interface.
>>
>> > I don't see a useful way to generalize this to other "both kinds" classes 
>> > (for
>> > example, any class with an instance field must be an identity class or a 
>> > value
>> > class). But since we have to make special allowances for Object one way or
>> > another, it does seem plausible that we let 'new Object()' continue to 
>> > create
>> > direct instances of class Object, and then specify the following special 
>> > rules:
>> >
>> > - All concrete, non-value classes are implicitly identity classes *except 
>> > for
>> > Object*
>> >
>> > - The 'new' bytecode is allowed to be used with concrete identity classes 
>> > *and
>> > class Object*
>> >
>> > - Identity objects include instances of identity classes, arrays, *and 
>> > instances
>> > of Object*; 'hasIdentity' reflects this
>> >
>> > - [anything else?]
>> >
>> > There's some extra complexity here, but balanced against the cost of making
>> > every Java programmer adjust their model of what 'new Object()' means, and
>> > corresponding coding style refactorings, it seems like a win.
>> >
>> > Thoughts?
>>
>> Seems like a win.
>>
> 
> The alternative - which we've been exploring till now - is to have the
> VM do some magic to turn:
> 
> 0: new  #2                  // class java/lang/Object
> 3: dup
> 4: invokespecial #1    // Method java/lang/Object."<init>":()V
> 
> into the `new` of a VM-specified Object subclass, and to allow
> invoking a super-class constructor on it rather than its own
> (remember, the instance is an Object subclass).
> 
> That's a lot of magic we can do away with through specification and
> some careful API design.  Seems like a win.

It is too magic for me, especially because
  new Object().getClass() != Object.class

> 
> The careful API design will be key as I can see a lot of corner cases
> related to `obj.getClass().isIdentityClass() != obj.hasIdentity()`.
> Do we have a sketch of what the apis for this would look like?  I'm
> assuming these are just for expository purposes as isIdentityClass()
> really needs to return a trinary value - {true, false, maybe}.

Whatever we choose, the VM doing a rewriting trick (**) or not,
the API is the same anyway and as you said it has to be carefully written.

We have several ways to frame the discrepancy around Object.class, one is to 
say that if Object acts as a class, it's an identity class,
if Object acts as a type (type of a parameter, a field, etc.) then it accepts 
both identity and value class.

I believe that most of the question about the Class as a type are better 
answered by using isAssignableFrom.
The case where someone needs to know if a type allows only identity class or 
only value class seems a weird question compared to, can i assign that value ?

So i think we may be fine by only implementing very few methods
 - Class.isValueClass() and
 - Class.isPrimitiveClass().

All other questions can be implemented in user code, by example
  type == Object.class || type.isInterface() || !type.isValueClass()


> 
> --Dan

Rémi

** and un-rewriting when the bytecode is asked through JVMTI ?

Reply via email to