Юри*_*нов 3 java jvm concatenation javac string-concatenation
在Java 9中,Oracle改进了String连接。现在"" + someBoolean变成invokedynamic带有StringConcatFabric.makeConcatbootstrap方法。该结构在运行时生成将您的字符串连接在一起的类。我想禁用此行为并回退到普通的旧字符串生成器。
因此,我认为javac具有执行我想要的功能的标志。但是我找不到。
字符串串联功能分为两部分。
在运行时
在Java 9+中,在运行时,字符串连接由StringConcatFactory类(javadoc)控制。那是因为在需要字符串连接的任何地方都会javac生成invokedynamic字节码到StringConcatFactory :: makeConcat`。
StringConcatFactory以枚举(源代码)的形式定义了几种用于运行时连接的策略。Strategy
您可以通过以下方式从命令行更改默认策略: -Djava.lang.invoke.stringConcat
要在运行时获取Java-8行为,您需要将其设置为BC_SB,代表“ Bytecode,StringBuilder”
为了完整性,以下是其他值:
/**
* 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
Run Code Online (Sandbox Code Playgroud)在编译时
正如Kayaman正确指出的那样,这种StringConcatFactory影响仅在运行时影响程序。字节码仍然会包含invokedynamic到StringConcatFactory哪里字符串连。有几种方法可以将呼叫重新发送给StringBuilder:
禁用此行为的最直接方法是将--release=8标志传递给javac,以强制生成Java-8兼容代码。但是,这不仅影响字符串连接。
更具针对性的选项是通过来专门控制串联-XDstringConcat=inline。
让我们以这段代码为例:
public class Print {
public static void main(String[] args) {
String foo = "a";
String bar = "b";
System.out.println(foo+bar);
}
}
Run Code Online (Sandbox Code Playgroud)
如果不带任何标志就对其进行编译,则会得到:
public class Print {
public Print();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String a
2: astore_1
3: ldc #3 // String b
5: astore_2
6: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
9: aload_1
10: aload_2
11: invokedynamic #5, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
16: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
19: return
}
Run Code Online (Sandbox Code Playgroud)
注意invokedynamic要makeConcatWithConstants。
但是,如果运行javac -XDstringConcat=inline Print.java,则会得到以下信息:
public class Print {
public Print();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String a
2: astore_1
3: ldc #3 // String b
5: astore_2
6: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
9: new #5 // class java/lang/StringBuilder
12: dup
13: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
16: aload_1
17: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: aload_2
21: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: invokevirtual #9 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
30: return
}
Run Code Online (Sandbox Code Playgroud)
就像Java 8一样,这里String是使用进行连接的StringBuilder。
| 归档时间: |
|
| 查看次数: |
86 次 |
| 最近记录: |