如何在Java 9中实现String连接? [英] How is String concatenation implemented in Java 9?

查看:146
本文介绍了如何在Java 9中实现String连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JEP 280 所述:


更改由 javac 生成的静态 String -concatenation字节码序列以使用 invokedynamic 调用JDK库函数。这将允许将来优化 String 连接,而无需进一步更改 javac 所包含的字节码。

Change the static String-concatenation bytecode sequence generated by javac to use invokedynamic calls to JDK library functions. This will enable future optimizations of String concatenation without requiring further changes to the bytecode emmited by javac.

这里我想了解 invokedynamic 调用的用法以及字节码串联与 invokedynamic

Here I want to understand what the use of invokedynamic calls is and how bytecode concatenation is different from invokedynamic?

推荐答案

旧方式输出一堆 StringBuilder - 面向操作。考虑这个程序:

The "old" way output a bunch of StringBuilder-oriented operations. Consider this program:

public class Example {
    public static void main(String[] args)
    {
        String result = args[0] + "-" + args[1] + "-" + args[2];
        System.out.println(result);
    }
}

如果我们用JDK 8或更早版本编译它然后使用 javap -c Example 查看字节码,我们看到如下内容:

If we compile that with JDK 8 or earlier and then use javap -c Example to see the bytecode, we see something like this:


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 并使用附加。这是着名的低效率,因为 StringBuilder 中内置缓冲区的默认容量只有16个字符,编译器无法使用知道提前分配更多,所以最终不得不重新分配。它也是一堆方法调用。 (请注意,JVM可以有时检测并重写这些调用模式,以提高它们的效率。)

As you can see, it creates a StringBuilder and uses append. This is famous fairly inefficient as the default capacity of the built-in buffer in StringBuilder is only 16 chars, and there's no way for the compiler to know to allocate more in advance, so it ends up having to reallocate. It's also a bunch of method calls. (Note that the JVM can sometimes detect and rewrite these patterns of calls to make them more efficient, though.)

让我们来看看Java是什么9生成:

Let's look at what Java 9 generates:


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
}

哦,我的但是更短。 :-)它从 makeConcatWithConstants /invoke/StringConcatFactory.html\"rel =noreferrer> StringConcatFactory ,在其Javadoc中说明这一点:

Oh my but that's shorter. :-) It makes a single call to makeConcatWithConstants from StringConcatFactory, which says this in its Javadoc:


有助于创建字符串连接方法的方法,可用于有效地连接已知类型的已知类型的参数,可能在类型调整和参数的部分评估之后。这些方法通常用作 invokedynamic 调用站点的引导方法,以支持Java编程的字符串连接功能语言。

Methods to facilitate the creation of String concatenation methods, that can be used to efficiently concatenate a known number of arguments of known types, possibly after type adaptation and partial evaluation of arguments. These methods are typically used as bootstrap methods for invokedynamic call sites, to support the string concatenation feature of the Java Programming Language.

这篇关于如何在Java 9中实现String连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆