• Post Reply Bookmark Topic Watch Topic
  • New Topic

string pool behavior  RSS feed

 
Richard Hayward
Ranch Hand
Posts: 167
10
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm trying to write a few tests to explore the behavior of the string pool.

My understanding is that any string literal appearing in the source code will get placed in the string pool.


So, at line 4, the strings "hello" and "world" will individually be in the pool, but not the string "hello world".
s0.intern() should therefore put the string "hello world" into the pool, where it was not present previously, and s0 and s1 should reference different objects. But they don't.

output:

Could anyone tell me why not?
 
Roel De Nijs
Sheriff
Posts: 11200
174
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Richard Hayward wrote:Could anyone tell me why not?

The intern() method works differently than your expectations

From the javadoc of the intern() method
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. Otherwise, this String object is added to the pool and a reference to this String object is returned.

In your example, the string "hello world" is not yet in the pool, so we have to focus on the second part of the above quote. In this case the intern() method will add the String object (referred by s0) to the pool. But no new String object is created and thus the same reference is returned. So that part of the intern() method could look like thisSo that's why s0 and s1 are referring to the same object.

If you add a copy of s0 to your code snippet, you'll notice that it refers to a different String object than s0 (or s1)And what happens if the String "hello world" was already present in the String Literal pool? Then the first part of the aforementioned quote is applicable, so s0 and s1 will refer to different objects, again illustrated in the following code snippet

Hope it helps!
Kind regards,
Roel
 
Richard Hayward
Ranch Hand
Posts: 167
10
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ah, thanks Roel.
Hope it helps!

Certainly yes! I had the wrong mental picture of what's going on there.

Could I additionally ask about garbage collection for strings in the pool?

Is there a difference, with respect to GC, between strings placed in the pool as a result of a source code literal and those placed there as a result of intern()?

I'm thinking that strings in the pool as a result of a source code literal are not subject to GC. However, attempting to test that, for strings in the pool as a consequence of intern():


as already discussed, but

indicating such strings are subject to GC. I realize that GC doesn't necessarily run just because I suggest that it does.
 
Roel De Nijs
Sheriff
Posts: 11200
174
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Richard Hayward wrote:Is there a difference, with respect to GC, between strings placed in the pool as a result of a source code literal and those placed there as a result of intern()?

Again from the javadoc of the intern() method
All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.


Luckily you don't need to worry about strings and GC on the actual exam...
 
Richard Hayward
Ranch Hand
Posts: 167
10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for your help Roel.

Roel De Nijs wrote:
Again from the javadoc of the intern() method
All literal strings and string-valued constant expressions are interned. String literals are defined in section 3.10.5 of the The Java™ Language Specification.


Ok, literals are interned, but I'm wondering if interned literals are still eligible for GC. Attempting to test that:

it's hard to tell. Maybe GC  didn't run or maybe it did, but strings in the pool put there as a result of appearing as literals in the source are not eligable for GC.
Roel De Nijs wrote:
Luckily you don't need to worry about strings and GC on the actual exam...

Anyway, if it's not needed for the exam, perhaps it's best for me to stop nitpicking over this particular issue.
 
Roel De Nijs
Sheriff
Posts: 11200
174
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Richard Hayward wrote:Ok, literals are interned, but I'm wondering if interned literals are still eligible for GC.

They probably are, but it will be (very) hard to test. For more info read this excellent article about the String.intern() method in Java 6, 7 and 8.
 
Tobias Bachert
Ranch Hand
Posts: 77
15
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
They are eligible for GC if the corresponding Class (and Classloader) is eligible for GC, i.e. the following prints true, false, true:
 
Ankit Garg
Sheriff
Posts: 9610
37
Android Google Web Toolkit Hibernate IntelliJ IDE Java Spring
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Although this is old, but on Java 6 or before since the pool was in PermGen, so following code results in false as the intern method call creates a new String in PermGen and s0 and s1 refer to different String objects:

 
Richard Hayward
Ranch Hand
Posts: 167
10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tobias Bachert wrote:They are eligible for GC if the corresponding Class (and Classloader) is eligible for GC, i.e. the following prints true, false, true:


Thanks Tobias, took me a little while to figure out what your example is doing, but that's instructive.
 
salman khandu
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,

String s1 = "Hello".concat("World");
String s3 = new String("HelloWorld"); //Line-2
String s2 = s1.intern();
System.out.println(s1 == s2); //false
System.out.println(s1 == s3); //false
System.out.println(s2 == s3); //false

If I removed Line-2 and compare s1==s2, it will return true. Could anyone explain me what exactly happens in string pool after Line-2?

Thanks
 
Roel De Nijs
Sheriff
Posts: 11200
174
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
salman khandu wrote:Could anyone explain me what exactly happens in string pool after Line-2?

That's already explained very well in this post.
 
Bhavin Akolkar
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,

Here I am getting confused with following two lines of code.

1) String s3 = new String("HelloWorld"); will return false for line System.out.println(s1 == s2);
2) String s3 = new String(s1); will return true for line System.out.println(s1 == s2);

What is the difference?
Can anyone please explain?

Thanks
 
Henry Wong
author
Sheriff
Posts: 23192
124
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
salman khandu wrote:
If I removed Line-2 and compare s1==s2, it will return true. Could anyone explain me what exactly happens in string pool after Line-2?


First, with line 2 in the program, "HelloWorld" is a string literal, and hence, it is in the string pool at the start of the program.

The s1 reference is assigned to a new instance -- due to the concat() call. The s2 reference is assigned to the instance in the string pool. These two are two different instances, and hence, the comparison is false.


Second, with line 2 not in the program, there is no "HelloWorld" string literal, and hence, no "HelloWorld" in the string pool at the start of the program.

The s1 reference is assigned to a new instance -- due to the concat() call. The intern() call will actually place the s1 instance into the pool, since "HelloWorld" is not in the pool. The s2 reference is then assigned to the instance in the string pool. And hence, s1 and s2 are pointing to the same instance, and hence, the comparison is true.

Henry
 
Roel De Nijs
Sheriff
Posts: 11200
174
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Bhavin Akolkar wrote:1) String s3 = new String("HelloWorld"); will return false for line System.out.println(s1 == s2);
2) String s3 = new String(s1); will return true for line System.out.println(s1 == s2);

What is the difference?
Can anyone please explain?

In short, in (1) "HelloWorld" is a string literal and it is in String Literal Pool at the start of the program; in (2) that's not the case. That's the difference and results in a different outcome for the s1 == s2 comparison. For a more detailed explanation please refer to this post.
 
Tobias Bachert
Ranch Hand
Posts: 77
15
  • Likes 3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Small correction: String literals are loaded lazily at first usage, not at the start of the program/loading of the class (behavior is not defined by the JVM specification).
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!