String intern puzzle

A String based puzzle for you.

The following program

String te = "te", st = "st";
// "test".length();
String username = te + st;
username.intern();
System.out.println("String object the same is: " 

    + (username == "test"));

prints under Java 7 update 7.

String object the same is: true

but uncomment the "test".length(); line, or run with Java 6 and it prints

String object the same is: false

Can you work out why?

Comments

  1. because te + st is computed in runtime unlike "te" + "st" which works on literals?

    in other words te + st is more like new String("test") which creates new object even if "test" already exists in the pool

    is that right?

    ReplyDelete
  2. String literals are interned automatically.

    Also the JavaDoc for String#intern() mentions:

    "When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned."

    Thus, username.intern() will return the "test" string from the pool but will not change the object reference of username and in the end username and "test" do not refer to the same String object (from the pool).

    ReplyDelete
  3. with commented "test".length() line:

    String object the same is: false

    jdk 1.6.0.24

    ReplyDelete
  4. case 1:
    the string "test" is not present in pool use, so the object username is added to pool. thus username=="test" becomes true

    case 2:
    the line "test".length() adds this string to pool. and the method call username.intern() return reference to the string in pool.
    so username=="test" returns false

    ReplyDelete
  5. I should have noted that this only happens under Java 7. Java 6 behaves differently.

    ReplyDelete
  6. Related links

    http://stackoverflow.com/questions/12278323/string-intern-puzzles

    http://stackoverflow.com/questions/7065337/intern-behaving-differently-in-java-6-and-java-7

    ReplyDelete
  7. I guess using == is commonly understood as the wrong way in Java to test string equality

    We are observing coincidences that happens in different situations in the constant pool, any future implementation may or may not surface such behaviour
    with no weight on compliance whatsoever

    this is very much like the insertion order of keys in a hash

    ReplyDelete
  8. Looks like java6 puts a copy to the pool, but java7 puts the object itself.

    ReplyDelete
  9. It is not a puzzle at all. It is a well known feature of JDK 7:

    In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but are instead allocated in the main part of the Java heap (known as the young and old generations), along with the other objects created by the application. This change will result in more data residing in the main Java heap, and less data in the permanent generation, and thus may require heap sizes to be adjusted. Most applications will see only relatively small differences in heap usage due to this change, but larger applications that load many classes or make heavy use of the String.intern() method will see more significant differences.

    ReplyDelete
  10. @ILLya Could you could talk about the changes in the JDK which explain the puzzle?

    ReplyDelete
    Replies
    1. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6962931

      Huhh. I missed this change...

      Delete

Post a Comment

Popular posts from this blog

Java is Very Fast, If You Don’t Create Many Objects

System wide unique nanosecond timestamps

Unusual Java: StackTrace Extends Throwable