title: Why does a Java string comparison behave different in Java 15 and Java 11?
body: <p>Please consider the following class:</p>
  <pre><code>class Eq {
    public static void main(String[] args) {
      System.out.println(&quot;&quot; == &quot;.&quot;.substring(1));
    }
  }
  </code></pre>
  <p>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 <code>false</code> as expected. Under OpenJDK 15, the program outputs <code>true</code>. The generated bytecode for the class files looks similar (even though they differ in register values):</p>
  <p>Java 11:</p>
  <pre><code>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
  </code></pre>
  <p>Java 15:</p>
  <pre><code>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
  </code></pre>
  <p>I tried to exclude static compiler optimizations by reading &quot;.&quot; from stdin but this does not change the outcome. I have tried to disable the JIT via <code>-Djava.compiler=NONE</code> and played around with adjusting the string table size via <code>-XX:StringTableSize=100000</code>. I now have the following questions:</p>
  <ul>
  <li>Can someone reproduce the issue (i.e. did I do it correctly? I can provide the class files if that helps)</li>
  <li>How do I find out the exact reason for the different behaviour?</li>
  <li>What (in your opinion) is the source for the different behaviour?</li>
  </ul>
  <p>I think just strategies to approach how to find the reason for the behaviour that don't answer the question might also be interesting.</p>