Moh*_*agi 108 java string string-concatenation invokedynamic java-9
正如JEP 280中所写:
更改
String生成的static -concatenation字节码序列,javac以使用invokedynamic对JDK库函数的调用.这将使未来的String串联优化成为可能,而无需进一步更改所设置的字节码javac.
在这里,我想了解invokedynamic调用的用途以及字节码串联的不同之处是invokedynamic什么?
T.J*_*der 93
"旧"方式输出一堆StringBuilder定向操作.考虑这个程序:
public class Example {
public static void main(String[] args)
{
String result = args[0] + "-" + args[1] + "-" + args[2];
System.out.println(result);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我们使用JDK 8或更早版本编译它然后javap -c Example用来查看字节码,我们会看到如下内容:
public class Example {
public Example();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class java/lang/StringBuilder
3: dup
4: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
7: aload_0
8: iconst_0
9: aaload
10: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
13: ldc #5 // String -
15: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: aload_0
19: iconst_1
20: aaload
21: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: ldc #5 // String -
26: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
29: aload_0
30: iconst_2
31: aaload
32: invokevirtual #4 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
35: invokevirtual #6 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
38: astore_1
39: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
42: aload_1
43: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
46: return
}
如您所见,它创建了一个StringBuilder并使用append.这是着名的低效率,因为内置缓冲区的默认容量StringBuilder只有16个字符,并且编译器无法预先分配更多,因此最终必须重新分配.它也是一堆方法调用.(请注意,JVM 有时可以检测并重写这些调用模式,以提高它们的效率.)
让我们看看Java 9生成的内容:
public class Example {
public Example();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: aload_0
1: iconst_0
2: aaload
3: aload_0
4: iconst_1
5: aaload
6: aload_0
7: iconst_2
8: aaload
9: invokedynamic #2, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
14: astore_1
15: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
18: aload_1
19: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: return
}
哦,我的,但那更短.:-)它对makeConcatWithConstantsfrom 进行一次调用StringConcatFactory,在Javadoc中说这个:
方便创建字符串连接方法的方法,可用于有效地连接已知类型的已知类型的参数,可能在类型调整和参数的部分评估之后.这些方法通常用作引导方法的
invokedynamic调用处,支持字符串连接 Java编程语言的特点.
Nam*_*man 20
在进入invokedynamic用于优化字符串连接的实现的细节之前,在我看来,必须得到一些关于什么是invokedynamic的背景知识以及如何使用它?
该
invokedynamic指令简化并可能改进JVM上动态语言的编译器和运行时系统的实现.它通过允许语言实现者使用invokedynamic涉及以下步骤的指令定义自定义链接行为来实现此目的.
我可能会尝试通过为实现字符串连接优化而带来的更改来引导您完成这些操作.
定义Bootstrap方法: - 使用Java9,invokedynamic调用站点的引导方法,主要支持字符串连接makeConcat,makeConcatWithConstants并随StringConcatFactory实现一起引入.
使用invokedynamic提供了在运行时选择转换策略的替代方法.使用的转换策略StringConcatFactory类似于LambdaMetafactory之前的java版本中引入的转换策略.此外,问题中提到的JEP的目标之一是进一步扩展这些策略.
指定常量池条目: - 这些是除了invokedynamic(1)MethodHandles.Lookup对象之外的指令的附加静态参数,该对象是用于在invokedynamic指令的上下文中创建方法句柄的工厂,(2)String对象,动态调用中提到的方法名称站点和(3)MethodType对象,动态调用站点的已解析类型签名.
在链接代码期间已经链接了.在运行时,引导方法运行并链接到实际代码中进行连接.它invokedynamic通过适当的invokestatic呼叫重写呼叫.这将从常量池加载常量字符串,利用bootstrap方法static args将这些和其他常量直接传递给bootstrap方法调用.
使用invokedynamic指令: - 通过在初始调用期间提供一次引导调用目标的方法,为延迟链接提供了便利.这里优化的具体想法是StringBuilder.append用简单的invokedynamic调用替换整个舞蹈java.lang.invoke.StringConcatFactory,这将接受需要连接的值.
所述Indify字符串连接建议用一个例子指出与Java9应用程序,其中一个相似的方法如通过共享的基准@TJ克劳德被编译并在字节码的差变化的执行之间相当可见.
Eug*_*ene 17
我在这里稍微添加一些细节.要获得的主要部分是字符串连接如何完成是运行时决定,而不是编译时间.因此它可以改变,这意味着您已经针对java-9编译了一次代码,并且它可以更改底层实现,但不需要重新编译.
第二点是目前有6 possible strategies for concatenation of String:
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
}
Run Code Online (Sandbox Code Playgroud)
您可以通过参数选择其中任何一个:-Djava.lang.invoke.stringConcat.请注意,这StringBuilder仍然是一个选项.
| 归档时间: |
|
| 查看次数: |
8315 次 |
| 最近记录: |