APIdia Launch Partner
Top Description Inners Fields Constructors Methods
java.lang.invoke

public final Class StringConcatFactory

extends Object
Class Inheritance
Annotations
@AOTSafeClassInitializer
Imports
jdk.internal.access.JavaLangAccess, .SharedSecrets, jdk.internal.constant.ClassOrInterfaceDescImpl, .ConstantUtils, .MethodTypeDescImpl, jdk.internal.misc.VM, jdk.internal.util.ClassFileDumper, .ReferenceKey, .ReferencedKeyMap, jdk.internal.vm.annotation.AOTSafeClassInitializer, .Stable, java.lang.classfile.Annotation, .ClassBuilder, .ClassFile, .CodeBuilder, .MethodBuilder, .TypeKind, java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute, java.lang.constant.ClassDesc, .MethodTypeDesc, java.lang.invoke.MethodHandles.Lookup, java.lang.ref.SoftReference, java.util.Map, .Objects, java.util.concurrent.ConcurrentHashMap, java.util.function.Consumer, .Supplier

Methods to facilitate the creation of String concatenation methods, that can be used to efficiently concatenate a known number of arguments of known types, possibly after type adaptation and partial evaluation of arguments. These methods are typically used as bootstrap methods for invokedynamic call sites, to support the string concatenation feature of the Java Programming Language.

Indirect access to the behavior specified by the provided MethodHandle proceeds in order through two phases:

  1. Linkage occurs when the methods in this class are invoked. They take as arguments a method type describing the concatenated arguments count and types, and optionally the String recipe, plus the constants that participate in the String concatenation. The details on accepted recipe shapes are described further below. Linkage may involve dynamically loading a new class that implements the expected concatenation behavior. The CallSite holds the MethodHandle pointing to the exact concatenation method. The concatenation methods may be shared among different CallSites, e.g. if linkage methods produce them as pure functions.
  2. Invocation occurs when a generated concatenation method is invoked with the exact dynamic arguments. This may occur many times for a single concatenation method. The method referenced by the behavior MethodHandle is invoked with the static arguments and any additional dynamic arguments provided on invocation, as if by MethodHandle#invoke(Object...).

This class provides two forms of linkage methods: a simple version (makeConcat(java.lang.invoke.MethodHandles.Lookup, String, MethodType)) using only the dynamic arguments, and an advanced version (makeConcatWithConstants(java.lang.invoke.MethodHandles.Lookup, String, MethodType, String, Object...) using the advanced forms of capturing the constant arguments. The advanced strategy can produce marginally better invocation bytecode, at the expense of exploding the number of shapes of string concatenation methods present at runtime, because those shapes would include constant static arguments as well.

API Note

There is a JVM limit (classfile structural constraint): no method can call with more than 255 slots. This limits the number of static and dynamic arguments one can pass to bootstrap method. Since there are potential concatenation strategies that use MethodHandle combinators, we need to reserve a few empty slots on the parameter lists to capture the temporal results. This is why bootstrap methods in this factory do not accept more than 200 argument slots. Users requiring more than 200 argument slots in concatenation are expected to split the large concatenation in smaller expressions.

Authors
Aleksey Shipilev, Remi Forax, Peter Levart
Since
9

Nested and Inner Type Summary

Modifier and TypeClass and Description
private static class
StringConcatFactory.InlineHiddenClassStrategy

Implement efficient hidden class strategy for String concatenation

This strategy replicates based on the bytecode what StringBuilders are doing: it builds the byte[] array on its own and passes that byte[] array to String constructor.

Field Summary

Modifier and TypeField and Description
private static MethodHandle
private static final int
private static MethodHandle
private static MethodHandle
private static MethodHandle
FLOAT_STRINGIFIER

Public gateways to public "stringify" methods.

private static final int
private static MethodHandle
private static final JavaLangAccess
private static MethodHandle
private static final int
MAX_INDY_CONCAT_ARG_SLOTS

Maximum number of argument slots in String Concat call.

private static MethodHandle
private static MethodHandle
private static final char
TAG_ARG

Tag used to demarcate an ordinary argument.

private static final char
TAG_CONST

Tag used to demarcate a constant.

Constructor Summary

AccessConstructor and Description
private

Method Summary

Modifier and TypeMethod and Description
private static StringConcatException
argumentMismatch(MethodType concatType, int oCount)

private static MethodHandle
private static MethodHandle
private static StringConcatException
constantMismatch(Object[] constants, int cCount)

private static MethodHandle
private static MethodHandle
private static MethodHandle
private static MethodHandle
public static CallSite

Returns:

a CallSite whose target can be used to perform String concatenation, with dynamic concatenation arguments described by the given concatType.
makeConcat
(MethodHandles.Lookup
Represents a lookup context with the accessibility privileges of the caller. Specifically, the lookup context must have full privilege access. When used with invokedynamic, this is stacked automatically by the VM.
lookup
,
String
The name of the method to implement. This name is arbitrary, and has no meaning for this linkage method. When used with invokedynamic, this is provided by the NameAndType of the InvokeDynamic structure and is stacked automatically by the VM.
name
,
MethodType
The expected signature of the CallSite. The parameter types represent the types of concatenation arguments; the return type is always assignable from java.lang.String. When used with invokedynamic, this is provided by the NameAndType of the InvokeDynamic structure and is stacked automatically by the VM.
concatType
)

Facilitates the creation of optimized String concatenation methods, that can be used to efficiently concatenate a known number of arguments of known types, possibly after type adaptation and partial evaluation of arguments.

public static CallSite

Returns:

a CallSite whose target can be used to perform String concatenation, with dynamic concatenation arguments described by the given concatType.
makeConcatWithConstants
(MethodHandles.Lookup
Represents a lookup context with the accessibility privileges of the caller. Specifically, the lookup context must have full privilege access. When used with invokedynamic, this is stacked automatically by the VM.
lookup
,
String
The name of the method to implement. This name is arbitrary, and has no meaning for this linkage method. When used with invokedynamic, this is provided by the NameAndType of the InvokeDynamic structure and is stacked automatically by the VM.
name
,
MethodType
The expected signature of the CallSite. The parameter types represent the types of dynamic concatenation arguments; the return type is always assignable from java.lang.String. When used with invokedynamic, this is provided by the NameAndType of the InvokeDynamic structure and is stacked automatically by the VM.
concatType
,
String
Concatenation recipe, described above.
recipe
,
Object...
A vararg parameter representing the constants passed to the linkage method.
constants
)

Facilitates the creation of optimized String concatenation methods, that can be used to efficiently concatenate a known number of arguments of known types, possibly after type adaptation and partial evaluation of arguments.

private static MethodHandle
private static MethodHandle
private static String[]
parseRecipe(MethodType concatType, String recipe, Object[] constants)

private static MethodHandle
private static MethodHandle
stringValueOf(Class<?> ptype)

private static MethodHandle
Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

BOOLEAN_STRINGIFIERback to summary
private static MethodHandle BOOLEAN_STRINGIFIER
Annotations
@Stable
CACHE_THRESHOLDback to summary
private static final int CACHE_THRESHOLD
CHAR_STRINGIFIERback to summary
private static MethodHandle CHAR_STRINGIFIER
Annotations
@Stable
DOUBLE_STRINGIFIERback to summary
private static MethodHandle DOUBLE_STRINGIFIER
Annotations
@Stable
FLOAT_STRINGIFIERback to summary
private static MethodHandle FLOAT_STRINGIFIER

Public gateways to public "stringify" methods. These methods have the form String apply(T obj), and normally delegate to String.valueOf, depending on argument's type.

Annotations
@Stable
FORCE_INLINE_THRESHOLDback to summary
private static final int FORCE_INLINE_THRESHOLD
INT_STRINGIFIERback to summary
private static MethodHandle INT_STRINGIFIER
Annotations
@Stable
JLAback to summary
private static final JavaLangAccess JLA
LONG_STRINGIFIERback to summary
private static MethodHandle LONG_STRINGIFIER
Annotations
@Stable
MAX_INDY_CONCAT_ARG_SLOTSback to summary
private static final int MAX_INDY_CONCAT_ARG_SLOTS

Maximum number of argument slots in String Concat call. While the maximum number of argument slots that indy call can handle is 253, we do not use all those slots, to let the strategies with MethodHandle combinators to use some arguments.

NEW_STRINGIFIERback to summary
private static MethodHandle NEW_STRINGIFIER
Annotations
@Stable
SIMPLE_CONCATback to summary
private static MethodHandle SIMPLE_CONCAT
Annotations
@Stable
TAG_ARGback to summary
private static final char TAG_ARG

Tag used to demarcate an ordinary argument.

TAG_CONSTback to summary
private static final char TAG_CONST

Tag used to demarcate a constant.

Constructor Detail

StringConcatFactoryback to summary
private StringConcatFactory()

Method Detail

argumentMismatchback to summary
private static StringConcatException argumentMismatch(MethodType concatType, int oCount)
booleanStringifierback to summary
private static MethodHandle booleanStringifier()
charStringifierback to summary
private static MethodHandle charStringifier()
constantMismatchback to summary
private static StringConcatException constantMismatch(Object[] constants, int cCount)
doubleStringifierback to summary
private static MethodHandle doubleStringifier()
floatStringifierback to summary
private static MethodHandle floatStringifier()
intStringifierback to summary
private static MethodHandle intStringifier()
longStringifierback to summary
private static MethodHandle longStringifier()
makeConcatback to summary
public static CallSite makeConcat(MethodHandles.Lookup lookup, String name, MethodType concatType) throws StringConcatException

Facilitates the creation of optimized String concatenation methods, that can be used to efficiently concatenate a known number of arguments of known types, possibly after type adaptation and partial evaluation of arguments. Typically used as a bootstrap method for invokedynamic call sites, to support the string concatenation feature of the Java Programming Language.

When the target of the CallSite returned from this method is invoked, it returns the result of String concatenation, taking all function arguments passed to the linkage method as inputs for concatenation. The target signature is given by concatType. For a target accepting:

  • zero inputs, concatenation results in an empty string;
  • one input, concatenation results in the single input converted as per JLS 5.1.11 "String Conversion"; otherwise
  • two or more inputs, the inputs are concatenated as per requirements stated in JLS 15.18.1 "String Concatenation Operator +". The inputs are converted as per JLS 5.1.11 "String Conversion", and combined from left to right.

Assume the linkage arguments are as follows:

  • concatType, describing the CallSite signature

Then the following linkage invariants must hold:

  • The number of parameter slots in concatType is less than or equal to 200
  • The return type in concatType is assignable from java.lang.String
Parameters
lookup:MethodHandles.Lookup

Represents a lookup context with the accessibility privileges of the caller. Specifically, the lookup context must have full privilege access. When used with invokedynamic, this is stacked automatically by the VM.

name:String

The name of the method to implement. This name is arbitrary, and has no meaning for this linkage method. When used with invokedynamic, this is provided by the NameAndType of the InvokeDynamic structure and is stacked automatically by the VM.

concatType:MethodType

The expected signature of the CallSite. The parameter types represent the types of concatenation arguments; the return type is always assignable from java.lang.String. When used with invokedynamic, this is provided by the NameAndType of the InvokeDynamic structure and is stacked automatically by the VM.

Returns:CallSite

a CallSite whose target can be used to perform String concatenation, with dynamic concatenation arguments described by the given concatType.

Exceptions
StringConcatException:
If any of the linkage invariants described here are violated, or the lookup context does not have private access privileges.
NullPointerException:
If any of the incoming arguments is null. This will never happen when a bootstrap method is called with invokedynamic.
Java Language Specification
5.1.11 String Conversion, 15.18.1 String Concatenation Operator +
makeConcatWithConstantsback to summary
public static CallSite makeConcatWithConstants(MethodHandles.Lookup lookup, String name, MethodType concatType, String recipe, Object... constants) throws StringConcatException

Facilitates the creation of optimized String concatenation methods, that can be used to efficiently concatenate a known number of arguments of known types, possibly after type adaptation and partial evaluation of arguments. Typically used as a bootstrap method for invokedynamic call sites, to support the string concatenation feature of the Java Programming Language.

When the target of the CallSite returned from this method is invoked, it returns the result of String concatenation, taking all function arguments and constants passed to the linkage method as inputs for concatenation. The target signature is given by concatType, and does not include constants. For a target accepting:

  • zero inputs, concatenation results in an empty string;
  • one input, concatenation results in the single input converted as per JLS 5.1.11 "String Conversion"; otherwise
  • two or more inputs, the inputs are concatenated as per requirements stated in JLS 15.18.1 "String Concatenation Operator +". The inputs are converted as per JLS 5.1.11 "String Conversion", and combined from left to right.

The concatenation recipe is a String description for the way to construct a concatenated String from the arguments and constants. The recipe is processed from left to right, and each character represents an input to concatenation. Recipe characters mean:

  • \1 (Unicode point 0001): an ordinary argument. This input is passed through dynamic argument, and is provided during the concatenation method invocation. This input can be null.
  • \2 (Unicode point 0002): a constant. This input passed through static bootstrap argument. This constant can be any value representable in constant pool. If necessary, the factory would call toString to perform a one-time String conversion.
  • Any other char value: a single character constant.

Assume the linkage arguments are as follows:

  • concatType, describing the CallSite signature
  • recipe, describing the String recipe
  • constants, the vararg array of constants

Then the following linkage invariants must hold:

  • The number of parameter slots in concatType is less than or equal to 200
  • The parameter count in concatType is equal to number of \1 tags in recipe
  • The return type in concatType is assignable from java.lang.String, and matches the return type of the returned MethodHandle
  • The number of elements in constants is equal to number of \2 tags in recipe

API Note

Code generators have three distinct ways to process a constant string operand S in a string concatenation expression. First, S can be materialized as a reference (using ldc) and passed as an ordinary argument (recipe '\1'). Or, S can be stored in the constant pool and passed as a constant (recipe '\2') . Finally, if S contains neither of the recipe tag characters ('\1', '\2') then S can be interpolated into the recipe itself, causing its characters to be inserted into the result.

Parameters
lookup:MethodHandles.Lookup

Represents a lookup context with the accessibility privileges of the caller. Specifically, the lookup context must have full privilege access. When used with invokedynamic, this is stacked automatically by the VM.

name:String

The name of the method to implement. This name is arbitrary, and has no meaning for this linkage method. When used with invokedynamic, this is provided by the NameAndType of the InvokeDynamic structure and is stacked automatically by the VM.

concatType:MethodType

The expected signature of the CallSite. The parameter types represent the types of dynamic concatenation arguments; the return type is always assignable from java.lang.String. When used with invokedynamic, this is provided by the NameAndType of the InvokeDynamic structure and is stacked automatically by the VM.

recipe:String

Concatenation recipe, described above.

constants:Object[]

A vararg parameter representing the constants passed to the linkage method.

Returns:CallSite

a CallSite whose target can be used to perform String concatenation, with dynamic concatenation arguments described by the given concatType.

Exceptions
StringConcatException:
If any of the linkage invariants described here are violated, or the lookup context does not have private access privileges.
NullPointerException:
If any of the incoming arguments is null, or any constant in recipe is null. This will never happen when a bootstrap method is called with invokedynamic.
Java Language Specification
5.1.11 String Conversion, 15.18.1 String Concatenation Operator +
makeSimpleConcatback to summary
private static MethodHandle makeSimpleConcat(MethodType mt, String[] constants)
newStringifierback to summary
private static MethodHandle newStringifier()
parseRecipeback to summary
private static String[] parseRecipe(MethodType concatType, String recipe, Object[] constants) throws StringConcatException
simpleConcatback to summary
private static MethodHandle simpleConcat()
stringValueOfback to summary
private static MethodHandle stringValueOf(Class<?> ptype)
unaryConcatback to summary
private static MethodHandle unaryConcat(Class<?> cl)
java.lang.invoke back to summary

private final Class StringConcatFactory.InlineHiddenClassStrategy

extends Object
Class Inheritance
  • java.lang.Object
  • java.lang.invoke.StringConcatFactory.InlineHiddenClassStrategy

Implement efficient hidden class strategy for String concatenation

This strategy replicates based on the bytecode what StringBuilders are doing: it builds the byte[] array on its own and passes that byte[] array to String constructor. This strategy requires access to some private APIs in JDK, most notably, the private String constructor that accepts byte[] arrays without copying.

Nested and Inner Type Summary

Modifier and TypeClass and Description
private static record

Field Summary

Modifier and TypeField and Description
pack-priv static final ReferencedKeyMap<MethodType, SoftReference<StringConcatFactory.InlineHiddenClassStrategy.MethodHandlePair>>
pack-priv static final ClassDesc
pack-priv static final ClassDesc
pack-priv static final ClassDesc
pack-priv static final ClassDesc
pack-priv static final ClassDesc
pack-priv static final String
pack-priv static final Consumer<CodeBuilder>
pack-priv static final MethodType
pack-priv static final ClassFileDumper
pack-priv static final RuntimeVisibleAnnotationsAttribute
pack-priv static final String
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodTypeDesc
pack-priv static final MethodHandles.Lookup

Constructor Summary

AccessConstructor and Description
private

Method Summary

Modifier and TypeMethod and Description
private static MethodTypeDesc
coderArgsIfMaybeUTF16(MethodType concatArgs)

Construct the MethodType of the coder method.

private static MethodType
erasedArgs(MethodType args)

The parameter types are normalized into 7 types: int,long,boolean,char,float,double,Object

private static MethodHandle
generate(MethodHandles.Lookup lookup, MethodType args, String[] constants)

private static Consumer<CodeBuilder>
generateCoderMethod(MethodTypeDesc coderArgs)

Generate coder method.

private static Consumer<CodeBuilder>
generateConcatMethod(boolean staticConcat, String[] constants, ClassDesc concatClass, MethodType concatArgs, MethodTypeDesc lengthArgs, MethodTypeDesc coderArgs, MethodTypeDesc prependArgs)

Generate InlineCopy-based code.

private static Consumer<CodeBuilder>
generateLengthMethod(MethodTypeDesc lengthArgs)

Generate length method.

private static Consumer<CodeBuilder>
generatePrependMethod(MethodTypeDesc prependArgs, boolean staticConcat, String[] constants)

Generate prepend method.

private static MethodTypeDesc
lengthArgs(MethodType concatArgs)

Construct the MethodType of the length method, The first parameter is the initialized length

pack-priv static boolean
pack-priv static boolean
private static MethodTypeDesc
prependArgs(MethodType concatArgs, boolean staticConcat)

Construct the MethodType of the prepend method, The parameters only support 5 types: int/long/char/boolean/String.

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

CACHEback to summary
pack-priv static final ReferencedKeyMap<MethodType, SoftReference<StringConcatFactory.InlineHiddenClassStrategy.MethodHandlePair>> CACHE
CD_Array_byteback to summary
pack-priv static final ClassDesc CD_Array_byte
CD_Array_Stringback to summary
pack-priv static final ClassDesc CD_Array_String
CD_CONCATback to summary
pack-priv static final ClassDesc CD_CONCAT
CD_StringConcatBaseback to summary
pack-priv static final ClassDesc CD_StringConcatBase
CD_StringConcatHelperback to summary
pack-priv static final ClassDesc CD_StringConcatHelper
CLASS_NAMEback to summary
pack-priv static final String CLASS_NAME
CONSTRUCTOR_BUILDERback to summary
pack-priv static final Consumer<CodeBuilder> CONSTRUCTOR_BUILDER
CONSTRUCTOR_METHOD_TYPEback to summary
pack-priv static final MethodType CONSTRUCTOR_METHOD_TYPE
DUMPERback to summary
pack-priv static final ClassFileDumper DUMPER
FORCE_INLINEback to summary
pack-priv static final RuntimeVisibleAnnotationsAttribute FORCE_INLINE
METHOD_NAMEback to summary
pack-priv static final String METHOD_NAME
MTD_byteback to summary
pack-priv static final MethodTypeDesc MTD_byte
MTD_byte_charback to summary
pack-priv static final MethodTypeDesc MTD_byte_char
MTD_INITback to summary
pack-priv static final MethodTypeDesc MTD_INIT
MTD_intback to summary
pack-priv static final MethodTypeDesc MTD_int
MTD_int_int_booleanback to summary
pack-priv static final MethodTypeDesc MTD_int_int_boolean
MTD_int_int_charback to summary
pack-priv static final MethodTypeDesc MTD_int_int_char
MTD_int_int_intback to summary
pack-priv static final MethodTypeDesc MTD_int_int_int
MTD_int_int_longback to summary
pack-priv static final MethodTypeDesc MTD_int_int_long
MTD_int_int_Stringback to summary
pack-priv static final MethodTypeDesc MTD_int_int_String
MTD_NEW_ARRAY_SUFFIXback to summary
pack-priv static final MethodTypeDesc MTD_NEW_ARRAY_SUFFIX
MTD_String_doubleback to summary
pack-priv static final MethodTypeDesc MTD_String_double
MTD_String_floatback to summary
pack-priv static final MethodTypeDesc MTD_String_float
MTD_STRING_INITback to summary
pack-priv static final MethodTypeDesc MTD_STRING_INIT
MTD_String_Objectback to summary
pack-priv static final MethodTypeDesc MTD_String_Object
PREPEND_booleanback to summary
pack-priv static final MethodTypeDesc PREPEND_boolean
PREPEND_charback to summary
pack-priv static final MethodTypeDesc PREPEND_char
PREPEND_intback to summary
pack-priv static final MethodTypeDesc PREPEND_int
PREPEND_longback to summary
pack-priv static final MethodTypeDesc PREPEND_long
PREPEND_Stringback to summary
pack-priv static final MethodTypeDesc PREPEND_String
STR_LOOKUPback to summary
pack-priv static final MethodHandles.Lookup STR_LOOKUP

Constructor Detail

InlineHiddenClassStrategyback to summary
private InlineHiddenClassStrategy()

Method Detail

coderArgsIfMaybeUTF16back to summary
private static MethodTypeDesc coderArgsIfMaybeUTF16(MethodType concatArgs)

Construct the MethodType of the coder method. The first parameter is the initialized coder. Only parameter types which can be UTF16 are added. Returns null if no such parameter exists or CompactStrings is off.

erasedArgsback to summary
private static MethodType erasedArgs(MethodType args)

The parameter types are normalized into 7 types: int,long,boolean,char,float,double,Object

generateback to summary
private static MethodHandle generate(MethodHandles.Lookup lookup, MethodType args, String[] constants) throws Exception
generateCoderMethodback to summary
private static Consumer<CodeBuilder> generateCoderMethod(MethodTypeDesc coderArgs)

Generate coder method.

The following is an example of the generated target code:

import static java.lang.StringConcatHelper.stringCoder;

static int cocder(int coder, char arg3, String str4, String str5, String str6, String str7) {
    return coder | stringCoder(arg3) | str4.coder() | str5.coder() | str6.coder() | str7.coder();
}
generateConcatMethodback to summary
private static Consumer<CodeBuilder> generateConcatMethod(boolean staticConcat, String[] constants, ClassDesc concatClass, MethodType concatArgs, MethodTypeDesc lengthArgs, MethodTypeDesc coderArgs, MethodTypeDesc prependArgs)

Generate InlineCopy-based code.

The following is an example of the generated target code:

 import static java.lang.StringConcatHelper.newArrayWithSuffix;
 import static java.lang.StringConcatHelper.prepend;
 import static java.lang.StringConcatHelper.stringCoder;
 import static java.lang.StringConcatHelper.stringSize;

 class StringConcat extends java.lang.StringConcatHelper.StringConcatBase {
     // super class defines
     // String[] constants;
     // int length;
     // byte coder;

     StringConcat(String[] constants) {
         super(constants);
     }

     String concat(int arg0, long arg1, boolean arg2, char arg3, String arg4,
         float arg5, double arg6, Object arg7
     ) {
         // Types other than byte/short/int/long/boolean/String require a local variable to store
         String str4 = stringOf(arg4);
         String str5 = stringOf(arg5);
         String str6 = stringOf(arg6);
         String str7 = stringOf(arg7);

         int coder  = coder(this.coder, arg0, arg1, arg2, arg3, str4, str5, str6, str7);
         int length = length(this.length, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
         String[] constants = this.constants;
         byte[] buf = newArrayWithSuffix(constants[paramCount], length. coder);

         prepend(length, coder, buf, constants, arg0, arg1, arg2, arg3, str4, str5, str6, str7);

         return new String(buf, coder);
     }

     static int length(int length, int arg0, long arg1, boolean arg2, char arg3,
                      String arg4, String arg5, String arg6, String arg7) {
         return stringSize(stringSize(stringSize(stringSize(stringSize(stringSize(stringSize(stringSize(
                     length, arg0), arg1), arg2), arg3), arg4), arg5), arg6), arg7);
     }

     static int cocder(int coder, char arg3, String str4, String str5, String str6, String str7) {
         return coder | stringCoder(arg3) | str4.coder() | str5.coder() | str6.coder() | str7.coder();
     }

     static int prepend(int length, int coder, byte[] buf, String[] constants,
                    int arg0, long arg1, boolean arg2, char arg3,
                    String str4, String str5, String str6, String str7) {
         // StringConcatHelper.prepend
         return prepend(prepend(prepend(prepend(
                 prepend(apppend(prepend(prepend(length,
                      buf, str7, constant[7]), buf, str6, constant[6]),
                      buf, str5, constant[5]), buf, str4, constant[4]),
                      buf, arg3, constant[3]), buf, arg2, constant[2]),
                      buf, arg1, constant[1]), buf, arg0, constant[0]);
     }
 }
generateLengthMethodback to summary
private static Consumer<CodeBuilder> generateLengthMethod(MethodTypeDesc lengthArgs)

Generate length method.

The following is an example of the generated target code:

import static java.lang.StringConcatHelper.stringSize;

static int length(int length, int arg0, long arg1, boolean arg2, char arg3,
                 String arg4, String arg5, String arg6, String arg7) {
    return stringSize(stringSize(stringSize(length, arg0), arg1), ..., arg7);
}
generatePrependMethodback to summary
private static Consumer<CodeBuilder> generatePrependMethod(MethodTypeDesc prependArgs, boolean staticConcat, String[] constants)

Generate prepend method.

The following is an example of the generated target code:

import static java.lang.StringConcatHelper.prepend;

static int prepend(int length, int coder, byte[] buf, String[] constants,
               int arg0, long arg1, boolean arg2, char arg3,
               String str4, String str5, String str6, String str7) {

    return prepend(prepend(prepend(prepend(
            prepend(prepend(prepend(prepend(length,
                 buf, str7, constant[7]), buf, str6, constant[6]),
                 buf, str5, constant[5]), buf, str4, constant[4]),
                 buf, arg3, constant[3]), buf, arg2, constant[2]),
                 buf, arg1, constant[1]), buf, arg0, constant[0]);
}
lengthArgsback to summary
private static MethodTypeDesc lengthArgs(MethodType concatArgs)

Construct the MethodType of the length method, The first parameter is the initialized length

maybeUTF16back to summary
pack-priv static boolean maybeUTF16(Class<?> cl)
needStringOfback to summary
pack-priv static boolean needStringOf(Class<?> cl)
prependArgsback to summary
private static MethodTypeDesc prependArgs(MethodType concatArgs, boolean staticConcat)

Construct the MethodType of the prepend method, The parameters only support 5 types: int/long/char/boolean/String. Not int/long/char/boolean type, use String type

The following is an example of the generated target code:

 int prepend(int length, byte coder, byte[] buff,  String[] constants
     int arg0, long arg1, boolean arg2, char arg3, String arg5)
java.lang.invoke back to summary

private final Record StringConcatFactory.InlineHiddenClassStrategy.MethodHandlePair

extends Record
Class Inheritance
Record Components
constructor:MethodHandle 
concatenator:MethodHandle 

Field Summary

Modifier and TypeField and Description
private final MethodHandle
concatenator

Record Component accessed by concatenator().

private final MethodHandle
constructor

Record Component accessed by constructor().

Constructor Summary

AccessConstructor and Description
private
MethodHandlePair(MethodHandle constructor, MethodHandle concatenator)

Method Summary

Modifier and TypeMethod and Description
public MethodHandle
concatenator()

Record Component getter of concatenator.

public MethodHandle
constructor()

Record Component getter of constructor.

public final boolean
equals(Object o)

Implements abstract java.lang.Record.equals.

Indicates whether some other object is "equal to" this one.

public final int
hashCode()

Implements abstract java.lang.Record.hashCode.

Returns a hash code value for the record.

public final String
toString()

Implements abstract java.lang.Record.toString.

Returns a string representation of the record.

Field Detail

concatenatorback to summary
private final MethodHandle concatenator

Record Component accessed by concatenator().

constructorback to summary
private final MethodHandle constructor

Record Component accessed by constructor().

Constructor Detail

MethodHandlePairback to summary
private MethodHandlePair(MethodHandle constructor, MethodHandle concatenator)

Method Detail

concatenatorback to summary
public MethodHandle concatenator()

Record Component getter of concatenator.

constructorback to summary
public MethodHandle constructor()

Record Component getter of constructor.

equalsback to summary
public final boolean equals(Object o)

Implements abstract java.lang.Record.equals.

Doc from java.lang.Record.equals.

Indicates whether some other object is "equal to" this one. In addition to the general contract of Object.equals, record classes must further obey the invariant that when a record instance is "copied" by passing the result of the record component accessor methods to the canonical constructor, as follows:

    R copy = new R(r.c1(), r.c2(), ..., r.cn());
then it must be the case that r.equals(copy).
hashCodeback to summary
public final int hashCode()

Implements abstract java.lang.Record.hashCode.

Doc from java.lang.Record.hashCode.

Returns a hash code value for the record. Obeys the general contract of Object.hashCode. For records, hashing behavior is constrained by the refined contract of Record.equals, so that any two records created from the same components must have the same hash code.

toStringback to summary
public final String toString()

Implements abstract java.lang.Record.toString.

Doc from java.lang.Record.toString.

Returns a string representation of the record. In accordance with the general contract of Object#toString(), the toString method returns a string that "textually represents" this record. The result should be a concise but informative representation that is easy for a person to read.

In addition to this general contract, record classes must further participate in the invariant that any two records which are equal must produce equal strings. This invariant is necessarily relaxed in the rare case where corresponding equal component values might fail to produce equal strings for themselves.