web-dev-qa-db-ja.com

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_22、およびJava 1.4.2_19で試しました。

javap -cから1.4.2_19を使用して表示されるバイトコードのサンプルを次に示します。

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バージョンから開始この変更が導入されましたか?

27
Nicolas C

バージョン1の言語仕様 からの引用です。

実装は、中間のStringオブジェクトを作成して破棄することを回避するために、変換と連結を1つのステップで実行することを選択できます。繰り返される文字列連結のパフォーマンスを向上させるために、JavaコンパイラはStringBufferクラス(§20.13)または同様の手法を使用して、式の評価によって作成される中間のStringオブジェクトの数を減らすことができます。 。

当時、彼らはStringBufferの代わりにStringBuilderを持っていました。

また、JDK1.0.2の StringBuffer からの引用:

このクラスは、文字の拡張可能なバッファーです。これは主に文字列を作成するために使用されます。コンパイラはこれを使用して「+」演算子を実装します。

31
manouti

Java言語仕様、初版(1996年から)を調べました。簡単な発見ではありませんが、 ここにあります 。連結最適化に関する一節もありました。その後:

実装は、中間のStringオブジェクトを作成して破棄することを回避するために、変換と連結を1つのステップで実行することを選択できます。繰り返される文字列連結のパフォーマンスを向上させるために、JavaコンパイラはStringBufferクラス(§20.13)または同様の手法を使用して、式の評価によって作成される中間Stringオブジェクトの数を減らすことができます。 。

その場合、仕様はStringBufferに関連しますが、StringBuilder(現在のJLSの表現で参照されている)は、メソッドが同期されていないため、パフォーマンスが優れていると見なされる場合があります。

ただし、これは、常にが実行されているため、最適化に依存する必要があることを意味するものではありません。たとえば、ループ内の文字列の連結は最適化されません。

11
lukeg

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:セクションを参照してください。

5

これは質問に答えませんですが、jdk-9ではこのStringBuilder::append許可された戦略の1つであるという全体的なポイントを追加したいだけですが、デフォルトのものではありません。

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

5
Eugene