Javac StringBuilder/StringBuffer 优化是什么时候引入的?

When was Javac StringBuilder/StringBuffer optimization introduced?

我知道 Javac 编译器能够使用 StringBuilder/StringBuffer 转换字符串连接 +,我很想知道 从哪个版本开始引入了这个变化?

我正在使用这个示例代码:

public class Main {
  public static void main(String[] args) {
      String a = args[0];
      String s = "a";
      s = s + a;
      s = s + "b";
      s = s + "c";
      s = s + "d";
      s = s + "e";
      System.out.println(s);
  }
}

到目前为止,我已经尝试使用 javac 1.8.0_121javac 1.6.0_20javac 1.5.0_22java 1.4.2_19

这是我使用 1.4.2_19 中的 javap -c 看到的字节码示例:

6:  astore_2
7:  new #3; //class StringBuffer
10: dup
11: invokespecial   #4; //Method java/lang/StringBuffer."<init>":()V
14: aload_2
15: invokevirtual   #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
18: aload_1
19: invokevirtual   #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
22: invokevirtual   #6; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;

所有 4 个版本似乎都在使用 StringBuilder/StringBuffer 优化,所以我很想知道 从哪个 Javac 版本 开始引入此更改?

引用自 language specification from version 1:

An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class (§20.13) or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.

当时,他们 StringBuffer 而不是 StringBuilder

也引自 JDK1.0.2 的StringBuffer

This Class is a growable buffer for characters. It is mainly used to create Strings. The compiler uses it to implement the "+" operator.

我查阅了 Java 语言规范,第一版(自 1996 年起)。不容易找到,但是 here it is。连接优化的段落甚至在那里:

An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class (§20.13) or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.

规范与 StringBuffer 有关,但 StringBuilder(当前 JLS 措辞所指)可能被认为性能更好,因为它的方法不是同步的。

然而,这并不意味着应该依赖优化,因为 always 就位。例如,循环中的字符串连接不会得到优化。

JLS已经在一些答案中给出了。我只想指出 StringBuffer (https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html) 自 1.0 以来就存在,而

StringBuilder(https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html) 出现在版本 1.5 中。请参阅相应 javadoc 的 since: 部分。

这没有回答问题,但我只想补充一点,在 jdk-9 中,这个 StringBuilder::append允许的策略之一,但不是默认策略。

private enum Strategy {
   /**
    * Bytecode generator, calling into {@link java.lang.StringBuilder}.
    */
    BC_SB,

    /**
     * Bytecode generator, calling into {@link java.lang.StringBuilder};
     * but trying to estimate the required storage.
     */
    BC_SB_SIZED,

    /**
     * Bytecode generator, calling into {@link java.lang.StringBuilder};
     * but computing the required storage exactly.
     */
     BC_SB_SIZED_EXACT,

   /**
    * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
    * This strategy also tries to estimate the required storage.
    */
    MH_SB_SIZED,

    /**
     * MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
     * This strategy also estimate the required storage exactly.
     */
    MH_SB_SIZED_EXACT,

    /**
     * MethodHandle-based generator, that constructs its own byte[] array from
     * the arguments. It computes the required storage exactly.
     */
     MH_INLINE_SIZED_EXACT
}

它实际上是一个用于字符串连接的 invokedynamic 字节码,因此它的实现现在是 JRE 特定的,而不是编译器的。顺便说一句,默认策略是:MH_INLINE_SIZED_EXACT