为什么 Java 字符串比较在 Java 15 和 Java 11 中的行为不同?
请考虑以下类:
class Eq {
public static void main(String[] args) {
System.out.println("" == ".".substring(1));
}
}
该示例应该表明内存中可能存在空字符串的多个副本。我仍然有一个旧的OpenJDK 11,其中程序按预期输出。在 OpenJDK 15 下,程序输出 。为类文件生成的字节码看起来很相似(即使它们在寄存器值上有所不同):false
true
Java 11:
public static void main(java.lang.String[]);
Code:
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #13 // String
5: ldc #15 // String .
7: iconst_1
8: invokevirtual #17 // Method java/lang/String.substring:(I)Ljava/lang/String;
11: if_acmpne 18
14: iconst_1
15: goto 19
18: iconst_0
19: invokevirtual #23 // Method java/io/PrintStream.println:(Z)V
22: return
Java 15:
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String
5: ldc #4 // String .
7: iconst_1
8: invokevirtual #5 // Method java/lang/String.substring:(I)Ljava/lang/String;
11: if_acmpne 18
14: iconst_1
15: goto 19
18: iconst_0
19: invokevirtual #6 // Method java/io/PrintStream.println:(Z)V
22: return
我试图通过从stdin中读取“.”来排除静态编译器优化,但这不会改变结果。我尝试通过禁用JIT,并通过调整字符串表大小进行了尝试。我现在有以下问题:-Djava.compiler=NONE
-XX:StringTableSize=100000
- 有人可以重现问题吗(即我是否正确执行了该问题?如果有帮助,我可以提供类文件)
- 我如何找出不同行为的确切原因?
- (在你看来)不同行为的来源是什么?
我认为,仅仅找到没有回答问题的行为原因的策略也可能很有趣。