当前位置: 首页 > 知识库问答 >
问题:

JDK 17 中字符串的 “” 操作数的优化

施辉
2023-03-14

我们知道,在JDK8及以下版本中,使用加号表示连接的字符串将被编译到StringBuilder中进行性能优化,但在JDK9之后,它将使用<code>java.lang.invoke实现。StringConcatFactory#makeConcatWithConstants方法。

但是,在反编译< code>java.lang.Object之后,可以看到其< code>toString方法仍然是使用StringBuilder实现的:

public java.lang.String toString();
descriptor: ()Ljava/lang/String;
flags: (0x0001) ACC_PUBLIC
Code:
  stack=2, locals=1, args_size=1
     0: new           #1                  // class java/lang/StringBuilder
     3: dup
     4: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
     7: aload_0
     8: invokevirtual #7                  // Method getClass:()Ljava/lang/Class;
    11: invokevirtual #13                 // Method java/lang/Class.getName:()Ljava/lang/String;
    14: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    17: ldc           #23                 // String @
    19: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    22: aload_0
    23: invokevirtual #25                 // Method hashCode:()I
    26: invokestatic  #29                 // Method java/lang/Integer.toHexString:(I)Ljava/lang/String;
    29: invokevirtual #19                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    32: invokevirtual #35                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    35: areturn
  LineNumberTable:
    line 256: 0
  LocalVariableTable:
    Start  Length  Slot  Name   Signature
        0      36     0  this   Ljava/lang/Object;

翻看源代码,可以看到它还是用加号来连接三个部分:

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

将相同的代码重写到一个类中进行编译:

public class Main {
    public String fooString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
}

从反编译可以看出,仍然是用< code > Java . lang . invoke . stringconcatfactory # makeConcatWithConstants 方法实现的:

public java.lang.String fooString();
    descriptor: ()Ljava/lang/String;
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
        start local 0 // Main this
         0: aload_0
         1: invokevirtual #7                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
         4: invokevirtual #11                 // Method java/lang/Class.getName:()Ljava/lang/String;
         7: aload_0
         8: invokevirtual #17                 // Method java/lang/Object.hashCode:()I
        11: invokestatic  #21                 // Method java/lang/Integer.toHexString:(I)Ljava/lang/String;
        14: invokedynamic #27,  0             // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
        19: areturn
        end local 0 // Main this
      LineNumberTable:
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      20     0  this   LMain;

那幺,为什么在<code>Object</code>类中使用加号是使用<code>StringBuilder</code>实现的,而类<code>A</code>(如上所述)是使用<code>makeConcatWithConstants</codes>实现的?JDK提供的Object类的字节码是否与源代码不匹配,或者在编译时是否对Object类进行了特殊优化

共有1个答案

伊裕
2023-03-14

JEP里有解释强调我的

豁免。由于此功能使用核心库功能(java.lang.invoke)来实现核心语言功能(字符串串联),因此我们必须免除 java.base 模块使用已识别的字符串连接。否则,当 java.lang.invoke.* 机制需要字符串连接才能工作时,就会发生循环性,而字符串连接又需要 java.lang.invoke.* 机制。这种豁免可能会限制从此功能中观察到的性能改进,因为许多 java.base 类将无法使用它。我们认为这是一个可以接受的缺点,VM的优化编译器应该涵盖这一点。

 类似资料:
  • 18.6. 优化字符串操作 Soundex 算法的最后一步是对短结果补零和截短长结果。最佳的做法是什么? 这是目前在 soundex/stage2/soundex2c.py 中的做法: digits3 = re.sub('9', '', digits2) while len(digits3) < 4: digits3 += "0" return digit

  • 我正在为MasterMind写一个求解器,其中我必须接受一个猜测和一个答案,并返回一些黑白钉子的数量表示,其中一个黑色钉子代表正确点的正确颜色,一个白色钉子代表不正确点的正确颜色。我必须运行这段代码大约200万次迭代,所以它需要尽可能快。目前最大的时间下沉是拆分和索引调用,但我不知道如何删除它们。关于如何在保持其功能的同时使代码运行得更快,有什么想法吗? 以确保清晰度。我的输入是用空格分隔的四种颜

  • 最大字符串为512M,但是大字符串非常不建议。

  • 问题 你想在字节字符串上执行普通的文本操作(比如移除,搜索和替换)。 解决方案 字节字符串同样也支持大部分和文本字符串一样的内置操作。比如: >>> data = b'Hello World' >>> data[0:5] b'Hello' >>> data.startswith(b'Hello') True >>> data.split() [b'Hello', b'World'] >>> dat

  • 前言 忙活了一个礼拜,终于等到周末,可以空下来写点东西。 之前已经完成《数值运算》和《布尔运算》,这次轮到介绍字符串操作 。咱们先得弄明白两个内容: 什么是字符串? 对字符串有哪些操作? 下面是"在线新华字典"的解释: 字符串:简称“串”。有限字符的序列。数据元素为字符的线性表,是一种数据的逻辑结构。在计算机中可有不同的存储结构。在串上可进行求子串、插入字符、删除字符、置换字符等运算。 而字符呢?

  • 字符串操作 函数 char *  rt_strstr (const char *s1, const char *s2)   判断字符串   rt_uint32_t  rt_strcasecmp (const char *a, const char *b)   忽略大小写比较字符串   char *  rt_strncpy (char *dst, const char *src, rt_ubase_