有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java何时引入Javac StringBuilder/StringBuffer优化?

我知道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版本开始引入这个更改


共 (4) 个答案

  1. # 1 楼答案

    以下是来自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:

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

  2. # 2 楼答案

    这并没有回答问题,但我只想补充一点,在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的,而不是编译器的。默认策略btw是:MH_INLINE_SIZED_EXACT

  3. # 3 楼答案

    我查阅了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措辞所指)可能被认为性能更好,因为它的方法不同步

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