Intern () behaves differently in Java 6 and Java 7

class Test { public static void main(String...args) { String s1 = "Good"; s1 = s1 + "morning"; System.out.println(s1.intern()); String s2 = "Goodmorning"; if (s1 == s2) { System.out.println("both are equal"); } } } 

This code produces different outputs in Java 6 and Java 7. In Java 6, the condition s1==s2 returns false , and in Java 7 s1==s2 returns true . Why?

Why does this program produce different output in Java 6 and Java 7?

+54
java string java-7 string-interning java-6
Aug 15 '11 at 13:13
source share
9 answers

It seems that JDK7 handles the experience differently, as before.
I tested it with line 1.7.0-b147 and got "both are equal", but when I execute it (the same bytecode) with 1.6.0_24 I do not get the message.
It also depends on where the String String b2 =... is in the source code. The following code also does not display a message:

 class Test { public static void main(String... args) { String s1 = "Good"; s1 = s1 + "morning"; String s2 = "Goodmorning"; System.out.println(s1.intern()); //just changed here s1.intern() and the if condition runs true if(s1 == s2) { System.out.println("both are equal"); } //now it works. } } 

it seems that intern after not finding a row in the row pool, inserts the actual instance of s1 into the pool. The JVM uses this pool when creating s2, so it gets the same link as s1. On the other hand, if s2 is created first, this link is stored in the pool.
This may be the result of moving interned strings from the ongoing generation of the Java heap.

Found here: Important RFEs Addressed in JDK 7

In JDK 7, interned strings are no longer allocated in the permanent generation of the Java heap, but instead are allocated in the main part of the Java heap (the so-called young and old generations) along with other created objects on request. This change will result in more data residing in the main Java heap and less data in the permanent generation, and therefore heap size adjustments may be required. Because of this change, most applications will only see relatively small differences in heap usage, but larger applications that load many classes or use the String.intern () method intensively will see more significant differences.

Not sure if this is an error and from which version ... JLS 3.10.5 Status

The result of explicitly interning the calculated string is the same string as any pre-existing literal string with the same contents.

so the question is how are pre-existing ones interpreted, compilation time or runtime: is Goodmorning already existing or not?
I prefer how it was implemented before 7 ...

+26
Aug 17 2018-11-11T00:
source share

Omit unnecessary data from the example:

 class Test { public static void main(String... args) { String s1 = "Good"; s1 = s1 + "morning"; System.out.println(s1 == s1.intern()); // Prints true for jdk7, false - for jdk6. } } 

Consider String#intern as a black box. Based on a few test cases, I would conclude that the implementation is as follows:

Java 6:
if the pool contains an object equal to this , then return the link to this object, otherwise create a new line (equal to this ), put in the pool and return the link to this created instance.

Java 7:
if the pool contains an object equal to this , then return the link to this object, else put this in the pool and return this .

Neither Java 6 nor Java 7 violate the method contract .

It appears that the new behavior of the mill method was the result of fixing this error: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6962931 .

+24
Aug 28 '11 at 23:59
source share

== compares links. The intern method ensures that strings with the same value have the same reference.

In javadoc for the String.intern method is explained:

public String intern ()

Returns the canonical representation for a string object.

The string pool, initially empty, is privately maintained by the String class.

When calling the intern method, if the pool already contains a string equal to this String object, defined by the equal (Object) method, then a string from the pool is returned. Otherwise, this String object is added to the pool and a link to this string is returned.

It follows that for any two lines s and t, s.intern () == t.intern () is true if and only if s.equals (t) are true.

All literals and string constant expressions are interned. String literals are defined in ยง3.10.5 of the Java Language Specification

Returns: a string that has the same contents as this string, but guaranteed from a pool of unique strings.

Therefore, without interning, the compiler looks at the constants in java code and builds its constant pool from it. There is another pool supported by the String class, and interning checks the string passed to the pool and ensures that the link is unique (so == will work).

+9
Aug 15 '11 at 13:16
source share

In jdk6: String s1="Good"; creates a String Good object in a persistent pool.

s1=s1+"morning"; creates another String morning object in the constant pool, but this time the JVM actually does: s1=new StringBuffer().append(s1).append("morning").toString(); .

Now that the new operator creates an object on the heap, so the link in s1 has a bunch, not a constant pool and String s2="Goodmorning"; creates a String object "Goodmorning" in a constant pool, the reference to which is stored in s2 .

Therefore, the condition if(s1==s2) is false.

But what happens in jdk7?

+7
Aug 17 2018-11-11T00:
source share

FIRST CASE:

In the first code snippet, you actually add three lines to the row pool. 1. s1 = "Good"
2. s1 = "Goodmorning" (after concatenation) 3. s2 = "Goodmorining"

By executing if (s1 == s2), the objects are the same, but the link is different, so it is false.

SECOND CASE:

In this case, you use s1.intern (), which means that if the pool already contains a string equal to this String object, as determined by the equals (Object) method, the string from the pool is returned. Otherwise, this String object is added to the pool and a reference is returned to this String object.

  • s1 = "Good"
  • s1 = "Goodmorning" (after concatenation)
  • For String s2 = "Goodmorning" a new line is not added to the pool and you get a link to the existing one for s2. Therefore, if (s1 == s2) returns true.
+6
Aug 18 '11 at 8:21
source share

You need to use s1.equals(s2) . Using == with String objects compares the object references themselves.

Edit: When I run the second piece of code, I do not get "both are equal."

Edit2: Clarified that links are compared when using '=='.

+5
Aug 15 '11 at 13:15
source share

There are basically 4 ways to compare strings:

  • "== operator": it just compares the reference variable of the string object. Thus, this may give you unexpected results depending on how you created the string, for example, using the constructor of the String classes or simply using a double quote, since you get memory in different ways (in the heap and pool, respectively).
  • "equals (Object) method": this is an object class method and an OVERLOADED string class. It compares the whole string and IS CASE SENSITIVE.
  • "equalsIgnoreCase (String) method": this is a string class method and compares the whole string and is NOT CORRECTED SENSITIVE.
  • "compares (String) method": compares both characters of a string by character and returns their difference, if the return value is 0, this means that the strings are equal.
+4
Aug 15 2018-11-15T00:
source share

Whenever you compare two strings, do not use == and use eqauls() becaue, you are comparing objects, not links:

 string1.equals(string2); 
+3
Aug 15 '11 at 13:17
source share

Result Code Id:

 class Test { public static void main(String... args) { String s1 = "Good"; s1 = s1 + "morning"; System.out.println(s1 == s1.intern()); // Prints true for jdk7, false - for jdk6. } } 

If you write like this:

 class Test { public static void main(String... args) { String s = "GoodMorning"; String s1 = "Good"; s1 = s1 + "morning"; System.out.println(s1 == s1.intern()); // Prints false for both jdk7 and jdk6. } } 

the reason is "ldC # N" (the loading string from the constant pool) and String.intern (), both will use StringTable in the JVM hotspot. For details, I wrote an article in the English pool: http://aprilsoft.cn/blog/post/307.html

+2
May 26 '12 at 2:11 a.m.
source share



All Articles