Record classfile and runtime API

Brian Goetz brian.goetz at
Sun Sep 1 18:22:36 UTC 2019

Thanks Remi; its a good time to revisit this.  The current strategy was a stake-in-the-ground, but needs to be refined before we finalize the design, as the bootstrap APIs are forever once we do that.

> The arguments of the bootstrap methods are redundant, you don't need to pass the record class because the Lookup object contains the record class (you have the API in Lookup to create an intermediary lookup from a Lookup and a class so no need to duplicate that information). For the first boostrap methods, the parameter containing "x;y" is due to the fact that a constant method handle is opaque by default so you can not get the corresponding field name. First, if you have the lookup that have created that object, you can get back the name with a "reveal". But i think here, the problem is that the arguments are the constant method handles and not the constant decriptor (ConstantDec).

Redundancy in and of itself is not necessarily bad.  Sure, you can get the class from the lookup, but then the bootstrap API is not exactly computing the same thing.  Maybe that’s OK,  maybe not, but the design should come first, not class file compression.  

Personally, I would prefer to have ONE bootstrap for all three methods (for example, using the invocation name to describe which method should be linked.)  Assumed we did that, what should the argument list be?  As you point out, specifying the name string as a single string (“x;y”) is a hack, so we should probably not do that.  Using reflection during linkage risks tradeing class file clarity for startup performance, which might not be a good trade.  There’s a lot of ways to slice this, but we want to choose something that works well on all the measures.  

If we had a common API, we could have a common meta-model constant that is resolved once and passed to all three methods.  Not sure that carries its weight, unless the meta-model object were exposed to users as well.  

> The java.lang.invoke API has currently the limitation that you can not use the ConstantDesc API to type values of the constant pool.

And, the code to put JLC constants in the constant pool isn’t there yet either (it originally was, but got pulled back waiting for “invoke” support in condy, which is coming soon.)

> Now we have to talk about the reflection API, currently the method that reflects the attribute Record is Class.getRecordAccessors() that returns an array of Method corresponding to the accessors and there are many things wrong with this method.

There are already plans to replace this with a proper reflective object (RecordComponent), this is just not done yet.

> So first, let's have a method getRecordComponentFields() in java.lang.Class that returns an array of

That’s just as bad as returning methods, probably worse (since the fields are private.)  Something more abstract is needed.  But the rest of what you say should work well with what we’ve got in the works.

> BTW, why do we need an extractor for a record ? we should not need one because we can inside the algorithm that create the pattern tree have a if class.isRecord() ? (the same way the serailization is specilized for enums by example).

Currently, it’s in there so we can prototype the following phase of pattern matching, deconstruction patterns on records.  But, even if records go in much earlier than deconstruction patterns, having the pattern support in the class file now is valuable, as we don’t want to create the problem of “you can use deconstruction on records, but you have to recompile your old record classifies first.”  

More information about the amber-spec-observers mailing list