Proposal: java.lang.runtime.Carrier

Maurizio Cimadamore maurizio.cimadamore at
Thu Mar 3 18:49:43 UTC 2022

Seems sensible.

As a possible "test", we could perhaps use this mechanism in the JDK 
implementation of LambdaForms? We do have places where we spin "species" 

(that said, maybe species classes contain a bit more than just data, so 
perhaps that's a wrong fit - but anyway, worth talking a look for 
possible code duplication).


On 03/03/2022 13:57, Jim Laskey wrote:
> We propose to provide a runtime /anonymous carrier class object 
> generator/; *java.lang.runtime.Carrier*. This generator class is 
> designed to share /anonymous classes/ when shapes are similar. For 
> example, if several clients require objects containing two integer 
> fields, then *Carrier* will ensure that each client generates carrier 
> objects using the same underlying anonymous class.
> Providing this mechanism decouples the strategy for carrier class 
> generation from the client facility. One could implement one class per 
> shape; one class for all shapes (with an Object[]), or something in 
> the middle; having this decision behind a bootstrap means that it can 
> be evolved at runtime, and optimized differently for different situations.
>       Motivation
> The String Templates JEP draft 
> <> proposes the 
> introduction of a /TemplatedString/ object for the primary purpose of 
> /carrying/ the /template/ and associated /values/ derived from a 
> /template literal/. To avoid value boxing, early prototypes described 
> these /carrier/objects using /per-callsite/ anonymous classes shaped 
> by value types, The use of distinct anonymous classes here is 
> overkill, especially considering that many of these classes are 
> similar; containing one or two object fields and/or one or two 
> integral fields. /Pattern matching/ has a similar issue when carrying 
> the values for the /holes/ of a pattern. With potentially hundreds 
> (thousands?) of template literals or patterns per application, we need 
> to find an alternate approach for these /value carriers/.
>       Description
> In general terms, the *Carrier* class simply caches anonymous classes 
> keyed on shape. To further increase similarity in shape, the ordering 
> of value types is handled by the API and not in the underlying 
> anonymous class. If one client requires an object with one object 
> value and one integer value and a second client requires an object 
> with one integer value and one object value, then both clients will 
> use the same underlying anonymous class. Further, types are folded as 
> either integer (byte, short, int, boolean, char, float), long (long, 
> double) or object. [We've seen that performance hit by folding the 
> long group into the integer group is significant, hence the separate 
> group.]
> The *Carrier* API uses MethodType parameter types to describe the 
> shape of a carrier. This incorporates with the primary use case where 
> bootstrap methods need to capture indy non-static arguments. The API 
> has three static methods;
> |// Return a constructor MethodHandle for a carrier with components // 
> aligning with the parameter types of the supplied methodType. static 
> MethodHandle constructor(MethodType methodType) // Return a component 
> getter MethodHandle for component i. static MethodHandle 
> component(MethodType methodType, int i) // Return component getter 
> MethodHandles for all the carrier's components. static MethodHandle[] 
> components(MethodType methodType)|
>       Examples
> |import java.lang.runtime.Carrier; ... // Define the carrier 
> description. MethodType methodType = 
> MethodType.methodType(Object.class, byte.class, short.class, 
> char.class, int.class, long.class, float.class, double.class, 
> boolean.class, String.class); // Fetch the carrier constructor. 
> MethodHandle constructor = Carrier.constructor(methodType); // Create 
> a carrier object. Object object = 
> (Object)constructor.invokeExact((byte)0xFF, (short)0xFFFF, 'C', 
> 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFFL, 1.0f / 3.0f, 1.0 / 3.0, true, 
> "abcde"); // Get an array of accessors for the carrier object. 
> MethodHandle[] components = Carrier.components(methodType); // Access 
> fields. byte b = (byte)components[0].invokeExact(object); short s = 
> (short)components[1].invokeExact(object); char c 
> =(char)components[2].invokeExact(object); int i = 
> (int)components[3].invokeExact(object); long l = 
> (long)components[4].invokeExact(object); float f 
> =(float)components[5].invokeExact(object); double d = 
> (double)components[6].invokeExact(object); boolean tf 
> (boolean)components[7].invokeExact(object); String s = 
> (String)components[8].invokeExact(object)); // Access a specific 
> field. MethodHandle component = Carrier.component(methodType, 3); int 
> ii = (int)component.invokeExact(object);|
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the amber-spec-experts mailing list