Classfile artifacts to support compilation/reflection

Brian Goetz brian.goetz at
Wed Apr 28 20:12:49 UTC 2021

I'm updating the SoV documents and it raises a few questions about what 
classfile surface we need for capturing the language model.  The good 
news is that with the single-classfile model, the translation complexity 
collapses almost to zero.  But there are a few questions of "what do we 
retain in the classfile."

1.  Ref-favoring vs val-favoring.  Whether a primitive class P is 
ref-favoring or val-favoring no longer affects translation of the 
classfile (yay), it only affects translation of _type uses_ of the 
unadorned name.  But, this has to be capture somewhere in the classfile, 
so that the compiler can read in P.class and know what the name `P` 
means.  There are a few choices here:

  - An ACC_ bit.  Meh, these are pretty expensive.
  - An attribute, which only javac and reflection would need to pay 
attention to.
  - A supertype (implements RefFavoring).

My preference is an attribute; this feels closest to `Signature` to me.  
Reflection might want to reflect the ref-favoring bit.

2.  Whether abstract classes are primitive superclass candidates.  The 
static compiler will check this at compilation time when it sees a 
superclass of a primitive class, but the JVM will want to recheck 
anyway.  There are two sensible ways to handle this in the classfile:

  - An attribute that says "I am a primitive superclass candidate."  The 
static compiler puts it there, and the JVM checks it.
  - Infer and tag.  If an abstract class is loaded that is not a 
primitive superclass candidate, the JVM injects IdentityObject as a 
superinterface of the newly loaded class; when we go to load a primitive 
subclass, this will fail because primitive classes cannot implement both 
IdentityObject and PrimitiveObject.

Reflection probably doesn't have to reflect whether a class is primitive 
superclass candidate; it already reflects the things needed to make this 

3.  T.ref.  In generic code, we can say `T.ref`, which is a total 
operator on types; if T is already a reference type, then T.ref = T, and 
if it is a primitive value type P.val., then T.ref = P.ref.  The 
Signature attribute should be extended to support the distinction 
between a use of `T` and a use of `T.ref`.  (T.val is partial, so 
doesn't make sense in the general case, and in the specific cases where 
it does make sense, does not currently look worth supporting.)

4.  Other flavors, as needed.  We've considered a "null-default" 
primitive class; if so, this has to be captured in a similar way as 
(1).  These can probably all be folded into a single PrimitiveClass 

More information about the valhalla-spec-observers mailing list