String interning riddle

I am struggling with the following riddle of my colleague:

public class App1 {
  public static void main(String[] args) {
    String s1 = "Ja".concat("va"); // seems to be interned?!
    String s2 = s1.intern();

    System.out.println(s1 == s2); // true
  }
}

The result is true . I'm a little surprised because it looks like s1interned. But this is not a constant expression, is it?

But then I am even more surprised why the following prints are false .

public class App2 {
  public static void main(String[] args) {
    String s1 = "Ja".concat("va"); // seems not to be interned?!
    String s3 = new String("Java"); // this changes output
    String s2 = s1.intern();

    System.out.println(s1 == s2); // false
  }
}

Why s3does the introduction change the result?

+6
source share
6 answers

The following are the rules that define Java String objects: String pool :

  • String , JVM , . , .
  • String new, , .
  • intern String, String , . intern .

,

String s1 = "Ja".concat("va");

concat String, , new .

 new String(buf, true)

, s1 .

, intern,

String s2 = s1.intern();

intern s1 String (, ). , s2 .

, s1 - , , . ,   (s1 == s2) false.

Java 1.8.0_92-b14

Java 8 . Java . intern concat, Java 8 new, Java. (checkOne - App1, checkTwo - App2),

  public static void checkOne();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=2, args_size=0
         0: ldc           #2                  // String Ja
         2: ldc           #3                  // String va
         4: invokevirtual #4                  // Method java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
         7: astore_0
         8: aload_0
         9: invokevirtual #5                  // Method java/lang/String.intern:()Ljava/lang/String;
        12: astore_1
        13: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
        16: aload_0
        17: aload_1
        18: if_acmpne     25
        21: iconst_1
        22: goto          26
        25: iconst_0
        26: invokevirtual #7                  // Method java/io/PrintStream.println:(Z)V
        29: return
      LineNumberTable:
        line 6: 0
        line 7: 8
        line 9: 13
        line 10: 29
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            8      22     0    s1   Ljava/lang/String;
           13      17     1    s2   Ljava/lang/String;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 25
          locals = [ class java/lang/String, class java/lang/String ]
          stack = [ class java/io/PrintStream ]
        frame_type = 255 /* full_frame */
          offset_delta = 0
          locals = [ class java/lang/String, class java/lang/String ]
          stack = [ class java/io/PrintStream, int ]

  public static void checkTwo();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=3, args_size=0
         0: ldc           #2                  // String Ja
         2: ldc           #3                  // String va
         4: invokevirtual #4                  // Method java/lang/String.concat:(Ljava/lang/String;)Ljava/lang/String;
         7: astore_0
         8: new           #8                  // class java/lang/String
        11: dup
        12: ldc           #9                  // String Java
        14: invokespecial #10                 // Method java/lang/String."":(Ljava/lang/String;)V
        17: astore_1
        18: aload_0
        19: invokevirtual #5                  // Method java/lang/String.intern:()Ljava/lang/String;
        22: astore_2
        23: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
        26: aload_0
        27: aload_2
        28: if_acmpne     35
        31: iconst_1
        32: goto          36
        35: iconst_0
        36: invokevirtual #7                  // Method java/io/PrintStream.println:(Z)V
        39: return
      LineNumberTable:
        line 13: 0
        line 14: 8
        line 15: 18
        line 17: 23
        line 18: 39
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            8      32     0    s1   Ljava/lang/String;
           18      22     1    s3   Ljava/lang/String;
           23      17     2    s2   Ljava/lang/String;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 35
          locals = [ class java/lang/String, class java/lang/String, class java/lang/String ]
          stack = [ class java/io/PrintStream ]
        frame_type = 255 /* full_frame */
          offset_delta = 0
          locals = [ class java/lang/String, class java/lang/String, class java/lang/String ]
          stack = [ class java/io/PrintStream, int ]
+6

intern , . , , intern on.

String s3 = new String("Java"), "Java", . s1.intern() s1.

+2

JDK 1.8.0_144. "false" . . .

"Ja".concat("va");, new String object. return java.lang.String#concat:

return new String(buf, true);

new, . (, String , , new, ).

s2 s1, , "Java" . , s1 s2 . s1 perm gen, s2 . , . false.

String s3 = new String("Java"); .

+2

App1 s1 "Java" String , App2 - "Java" , . :

App1

, "Java" main(), [ JRE].

String s1 = "Ja".concat("va");

"Java" , .

String s2 = s1.intern();

"Java" , s1 . , s1 s2 .

App2

String s3 = new String("Java");

. "Java" , , , , App2.

String s1 = "Ja".concat("va");

"Java" , App1.

String s2 = s1.intern();

"Java" , ( "Java" s3), . , s1 s2 , s1 - , s2 - .

, App2 "Java" , "Java" , .

, "Java" , , , JRE, App, "Java" , , JRE. - "hmkjlfhvjkh".

0

.


String s3 = new String("Java");

s3 Object; . , String "Java", , ( JLS).


String s2 = s1.intern();

javadoc, String , intern() , , .


String s1 = "Ja".concat("va");

"Java" .


, string '"Java" s1.intern(), . s1.

0

intern ( ):

When a method is called intern, if the pool already contains a string equal to this object String, as determined by the method equals(Object), then the string from the pool is returned. Otherwise, this object is Stringadded to the pool and a link to this object is returnedString .

-2
source

All Articles