Irfan Latif
Irfan Latif

Reputation: 667

How is string concatenation handled in Java bytecode compilation?

public class TestException extends Exception {

  public TestException(String msg) {
    super("This is the message: " + msg);
  }
}

The above code is compiled to:

public class TestException extends java.lang.Exception {
  public TestException(java.lang.String);
    Code:
       0: aload_0
       1: new           #1                  // class java/lang/StringBuilder
       4: dup
       5: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
       8: ldc           #7                  // String This is the message:
      10: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      13: aload_1
      14: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      17: invokevirtual #13                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      20: invokespecial #17                 // Method java/lang/Exception."<init>":(Ljava/lang/String;)V
      23: return
}

Here a StringBuilder object is created to concatenate the strings.

While in the same app at another place an exactly similar class is compiled to:

public class TestException extends java.lang.Exception {
  public TestException(java.lang.String);
    Code:
       0: aload_0
       1: aload_1
       2: invokedynamic #1,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
       7: invokespecial #5                  // Method java/lang/Exception."<init>":(Ljava/lang/String;)V
      10: return
}

Here StringConcatFactory.makeConcatWithConstants() is invoked to concatenate the strings.

Which factors determine this different behavior? How it can be predicted / controlled?


PS:
In the former case ldc instruction is called, which can be intercepted by overriding the MethodVisitor.visitLdcInsn() method and the String can be manipulated.

To address the latter behavior MethodVisitor.visitInvokeDynamicInsn() callback also needs to be overridden.

And I'm not sure if there are other possible behaviors too.

Upvotes: 0

Views: 201

Answers (1)

Irfan Latif
Irfan Latif

Reputation: 667

String concatenation behavior was changed in Java 9.

In the former case, the class belongs to the main app which was built using -source 8 -target 8. While in the latter case, the class belongs to a library which is (a dependency of the app but) built with -source 11 -target 11. So the compiled bytecode differs w.r.t. string concatenation.

Thanks to @Stephen C and @Kayaman for the links:


For the sake of completeness, as @Holger mentioned in comments, StringBuilder, String.concat() and String.join() are identical when it comes to string manipulation in the compiled bytecode. Because in all three cases the string constant is first pushed onto the stack using ldc (where it can be simply manipulated). But in the case of StringConcatFactory.makeConcatWithConstants(), references of local string variables are first pushed onto the stack using aload.

Upvotes: 0

Related Questions