makeConcat()
и makeConcatWithConstants()
, которые являются StringConcatFactory
точками входа API, обе используют doStringConcat()
, что дает CallSite
, используемое invokedynamic
.
doStringConcat()
звонки generate(Lookup, String, MethodType, Recipe)
, которые содержат следующий переключатель на перечисление, о котором вы спрашиваете:
switch (STRATEGY) {
case BC_SB:
return StringConcatFactory.BytecodeStringBuilderStrategy.generate(lookup, className, mt, recipe, StringConcatFactory.Mode.DEFAULT);
case BC_SB_SIZED:
return StringConcatFactory.BytecodeStringBuilderStrategy.generate(lookup, className, mt, recipe, StringConcatFactory.Mode.SIZED);
case BC_SB_SIZED_EXACT:
return StringConcatFactory.BytecodeStringBuilderStrategy.generate(lookup, className, mt, recipe, StringConcatFactory.Mode.SIZED_EXACT);
case MH_SB_SIZED:
return StringConcatFactory.MethodHandleStringBuilderStrategy.generate(mt, recipe, StringConcatFactory.Mode.SIZED);
case MH_SB_SIZED_EXACT:
return StringConcatFactory.MethodHandleStringBuilderStrategy.generate(mt, recipe, StringConcatFactory.Mode.SIZED_EXACT);
case MH_INLINE_SIZED_EXACT:
return StringConcatFactory.MethodHandleInlineCopyStrategy.generate(mt, recipe);
default:
throw new StringConcatException("Concatenation strategy " + STRATEGY + " is not implemented");
}
BytecodeStringBuilderStrategy
ручки BC_SB
, BC_SB_SIZED
и BC_SB_SIZED_EXACT
. Он генерирует тот же StringBuilder
-используемый байт-код, который javac
сгенерировал бы, если бы вы просто написали конкатенацию в своем Java-коде. Основное отличие состоит в том, что этот байт-код генерируется во время выполнения (а не во время компиляции) и загружается с использованием Unsafe.defineAnonymousClass()
.
MethodHandleStringBuilderStrategy
ручки MH_SB_SIZED
и MH_SB_SIZED_EXACT
. Он использует механизм MethodHandle
(включая композицию MethodHandle
) для построения той же цепочки конкатенации поверх вызовов StringBuilder
. Он не использует частные API (например, Unsafe
), поэтому это, вероятно, наименее непереносимая стратегия.
MethodHandleInlineCopyStrategy
ручки MH_INLINE_SIZED_EXACT
. Он также использует механизм MethodHandle
для построения цепочки конкатенации с композицией MethodHandle
, но вместо StringBuffer
он работает напрямую с байтовым массивом, избегая копирования, где это возможно. Для этого он использует некоторые внутренние API и некоторые знания о деталях реализации JDK (например, конструктор String
, который избегает копирования строковых байтов). Таким образом, эта реализация более хрупкая (для изменений JDK), но она также обеспечивает большую скорость.
Небольшое резюме
Мы можем видеть, что три отличаются в двух аспектах: a) что используется в качестве буфера для построения строки и b) как создается цепочка конкатенации.
BytecodeStringBuilderStrategy
(BC_SB_xxx
) использует StringBuilder
и генерацию кода времени выполнения.
MethodHandleStringBuilderStrategy
(MH_SB_xxx
) использует StringBuilder
и MethodHandle
s
MethodHandleInlineCopyStrategy
(MH_INLINE_SIZED_EXACT
) использует байтовый массив и MethodHandle
с.