Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a Java string comparison behave different in Java 15 and Java 11?

Please consider the following class:

class Eq {   public static void main(String[] args) {     System.out.println("" == ".".substring(1));   } } 

The example is supposed to show that multiple copies of the empty string may exist in memory. I still have an old OpenJDK 11 where the program outputs false as expected. Under OpenJDK 15, the program outputs true. The generated bytecode for the class files looks similar (even though they differ in register values):

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 

I tried to exclude static compiler optimizations by reading "." from stdin but this does not change the outcome. I have tried to disable the JIT via -Djava.compiler=NONE and played around with adjusting the string table size via -XX:StringTableSize=100000. I now have the following questions:

  • Can someone reproduce the issue (i.e. did I do it correctly? I can provide the class files if that helps)
  • How do I find out the exact reason for the different behaviour?
  • What (in your opinion) is the source for the different behaviour?

I think just strategies to approach how to find the reason for the behaviour that don't answer the question might also be interesting.

like image 743
lambda.xy.x Avatar asked Dec 03 '20 21:12

lambda.xy.x


People also ask

What is the difference between Java 8 and 11?

It is an open-source reference implementation of Java SE platform version 11. Java 11 was released after four years of releasing Java 8. Java 11 comes with new features to provide more functionality. Below are the features which are added in the four and a half years in between these two versions.

What are the different ways to compare Java string?

There are three ways to compare String in Java: By Using equals() Method. By Using == Operator. By compareTo() Method.

What is the best way to compare strings in Java?

To compare these strings in Java, we need to use the equals() method of the string. You should not use == (equality operator) to compare these strings because they compare the reference of the string, i.e. whether they are the same object or not.


1 Answers

This is mentioned in the JDK 15 Release Notes.

It was changed as requested by JDK-8240094:

JDK-8240094 : Optimize empty substring handling

String.substring return "" in some cases, but could be improved to do so in all cases when the substring length is zero.

Related:

JDK-8240225 : Optimize empty substring handling

Optimize String.substring and related operations like stripLeading, stripTrailing to avoid redundantly creating a new empty String.

Sub Task:

JDK-8251556 : Release Note: Optimized Empty Substring Handling

The implementation of String.substring and related methods stripLeading and stripTrailing have changed in this release to avoid redundantly creating a new empty String. This may impact code that depends on unspecified behaviour and the identity of empty sub-strings.

like image 116
Andreas Avatar answered Sep 18 '22 14:09

Andreas