Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Confusion with String object (String Pool & Garbage Collection)

 
Suketu Patel
Greenhorn
Posts: 23
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi all,

After reading the article http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html and the detail provided in the book OCA: Oracle Certified Associate Java SE 8 Programmer I Study Guide: Exam 1Z0-808 by Jeanne Boyarsky... On the topic of String pool (Garbage collection of the string literal).

Corey McGlone has said in artical under the topic Garbage Collection:

What makes an object eligible for garbage collection? If you're preparing for the SCJP exam (or even if you're not), the answer to that question should roll right off your tongue. An object is eligible for garbage collection when it is no longer referenced from an active part of the application. Anyone see what is special about garbage collection for String literals? Let's look at an example and see if you can see where this is going.

public class ImmutableStrings {
public static void main(String[] args) {
String one = "someString";
String two = new String("someString");
one = two = null;
} }

Just before the main method ends, how many objects are available for garbage collection? 0? 1? 2?

The answer is 1. Unlike most objects, String literals always have a reference to them from the String Literal Pool. That means that they always have a reference to them and are, therefore, not eligible for garbage collection.
As you can see, even though neither of our local variables, one or two, refer to our String object, there is still a reference to it from the String Literal Pool. Therefore, the object is not elgible for garbage collection. The object is always reachable through use of the intern() method, as referred to earlier.
In general, String Literals are not eligible for garbage collection. Ever.


Whereas in the above book on page 111 Jeanne says:

A small program can create a lot of String objects very quickly. For example, how many
do you think this piece of code creates?

10: String alpha = "";
11: for(char current = 'a'; current <= 'z'; current++)
12: alpha += current;
13: System.out.println(alpha);

The empty String on line 10 is instantiated, and then line 12 appends an "a". However,
because the String object is immutable, a new String object is assigned to alpha and the
“” object becomes eligible for garbage collection. The next time through the loop, alpha is
assigned a new String object, "ab", and the "a" object becomes eligible for garbage
collection. The next iteration assigns alpha to "abc" and the "ab" object becomes eligible
for garbage collection, and so on.

This sequence of events continues, and after 26 iterations through the loop, a total of 27
objects are instantiated, most of which are immediately eligible for garbage collection.


As per article any String literal object referencing through String pool never been able for garbage collection... Whereas book says different thing... ???
When I've tried this code... (Even I don't know much about intern() method)...


intern() method is only works before setting any reference variable with null value, but not after that... If we use, it throws an nullpointerException at run time. *** Does this means that the object has already been finalized by garbage collection???***

So how does this thing exactly works???
I know this is out of the scope of the OCA exam but still if you can help me sort this out?

Thanks,
S B Patel
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
S B Patel wrote:As per article any String literal object referencing through String pool never been able for garbage collection... Whereas book says different thing... ?

The article is correct and the study guide is wrong! A String literal is referenced from the String Literal Pool. So when a reference variable refers to a String literal and another String object (or literal) is assigned to this reference variable, the String literal will not be eligible for garbage collection, as it is still referenced from the String Literal Pool.
So in the code snippet on line10, reference variable alpha refers to the String literal "" (the empty String). On the 1st iteration of the loop 'a' is concatenated to the empty String creating a new String object "a" which is assigned to reference variable alpha. At this moment reference variable alpha is referring to the String object "a" and thus doesn't refer anymore to the empty String "". The empty String "" is not eligible for GC (as it's still referenced from the String Literal Pool). On the 2nd iteration of the loop 'b' is concatenated to the String object "a" creating a new String object "ab" which is assigned to reference variable alpha. At this moment reference variable alpha is referring to the String object "ab" and thus doesn't refer anymore to the String object "a". The String "a" is not a String literal and isn't referred to anymore, so this object is eligible for GC.
This topic covers exactly the same code snippet and is definitely worth reading.

S B Patel wrote:When I've tried this code... (Even I don't know much about intern() method)...

The intern() method adds the String object to the String Literal Pool if this String doesn't exist already in the String Literal Pool. If the String object/literal already existed in the String Literal Pool, the reference value of this String object/literal is simply returned. Very easy to illustrate with an example:On line1 the String literal "Java" is assigned to reference variable str1. The String literal "Java" will also exist in the String Literal Pool. On line2 a new String object is created based on an array of characters. The value of this String object is "Java" as well, but it's not a literal so this String is different from the String literal "Java" in the String Literal Pool. On line3, the String object to which str2 is referring, is added to the String Literal Pool. But because this string already exists in the String Literal Pool, the string from the pool is returned (and thus both str1 and str3 will refer to the same object).
If you execute the Intern class, you'll get this output which confirms the given explanation:
str1 & str2 same object? false
str1 & str2 same value? true
str1 & str3 same object? true
str1 & str3 same value? true
str2 & str3 same object? false
str2 & str3 same value? true


S B Patel wrote:intern() method is only works before setting any reference variable with null value, but not after that... If we use, it throws an nullpointerException at run time. *** Does this means that the object has already been finalized by garbage collection???***

If you set a String reference variable to null it doesn't refer to a String object anymore. So if you invoke any method on the String reference variable, you'll get a NullPointerException. This is not related to the intern() method, but will happen with any method from the String class. So if you change line21 in your code snippet to int four = one.length();, you'll get a NullPointerException as well.
And just for completeness: the NullPointerException won't happen on line22 as the comment in your code snippet suggests, but it does happen on the line before (line21) because you invoke an instance method on a null reference.

Hope it helps!
Kind regards,
Roel
 
Suketu Patel
Greenhorn
Posts: 23
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Roel De Nijs, now my doubt about String literal pool and garbage collection is almost clear.

The points I got are:
1) String assign to any reference variable with "" is a String literal and goes in the String literal pool, and never been eligible for garbage collection.
2) All String objects other than a String literal is only eligible for garbage collection.

for e.g.



s is set to null but "abc" String literal is alive in background in String literal pool until the program runs



At Line 1 a new object with string "abc" is created on the heap and not on a String literal pool b'z it's not a String literal
At Line two s1 is eligible for garbage collection... and thus "abc" also be garbage collected because it is not on String literal pool


How about this...

Comments about the code snippet:
  • Line 1 (Object and not String Literal)
  • Line 2 (Must be an Object and not String Literal)
  • Line 3 (Now s is String Literal... The old object s with "abcdef" is eligible for garbage collection)
  • After either of last two statements at Line 4 or Line 5 s is an reference to an Object "abcdefgh" OR "abcd" and not a String Literal any more, String Literal s on line 3 is not reference to s anymore but still alive in String Literal Pool


  • I've got your points on intern() method as well.

    If I'm still misunderstood please correct me.

    Thanks for your kind help,
    S B Patel
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Let's go quickly through your comments and code snippets.

    S B Patel wrote:1) String assign to any reference variable with "" is a String literal and goes in the String literal pool, and never been eligible for garbage collection.
    2) All String objects other than a String literal is only eligible for garbage collection.

    Any String literal (e.g. "I'm a String literal!") will be added once to the String Literal Pool. So this pool will always refer to the String literals and therefore a String literal will never be eligible for GC. When a String object is created at runtime, it is not a literal and therefore won't be referenced from the String Literal Pool. When a String object (not a literal) is no longer referenced from an active reference variable, it's eligble for GC.

    S B Patel wrote:s is set to null but "abc" String literal is alive in background in String literal pool until the program runs

    Correct!

    S B Patel wrote:At Line 1 a new object with string "abc" is created on the heap and not on a String literal pool b'z it's not a String literal
    At Line two s1 is eligible for garbage collection... and thus "abc" also be garbage collected because it is not on String literal pool

    This example is already quite tricky! On line1 you'll have the String literal "abc" (which will be added to the String Literal Pool). And also the new operator creates a new String object (not a String literal) with the same content as the String literal "abc". This newly created object is assigned to reference variable s1 (and is not a literal so it's not added to the String Literal Pool). On line2 null is assigned to reference variable s1, so the String object (not the literal) created on the previous line is no longer referenced by any (active) reference variable (because the only reference variable referring to this object, s1, is set to null) and thus is this String object eligible for GC. The String literal "abc" is still referred from the String Literal Pool and thus not eligible for GC.

    S B Patel wrote:Comments about the code snippet:
    - Line 1 (Object and not String Literal)
    - Line 2 (Must be an Object and not String Literal)
    - Line 3 (Now s is String Literal... The old object s with "abcdef" is eligible for garbage collection)
    - After either of last two statements at Line 4 or Line 5 s is an reference to an Object "abcdefgh" OR "abcd" and not a String Literal any more, String Literal s on line 3 is not reference to s anymore but still alive in String Literal Pool

    Most of your comments/explanation about the code snippet are wrong! So I'll provide a step-by-step explanation about what's happening on each line. Fasten your seatbelt. Ready? Here we go!
    1/ On line1 exactly the same happens as in the previous code snippet: the String literal "abcd" is added to the String Literal Pool and a new String object (not a String literal) is created with the same content as the String literal "abcd". This newly created object is assigned to reference variable s (and is not added to the String Literal Pool).
    2/ On line2 the String literal "ef" is added to the String Literal Pool and a new String object (not a String literal) is created: the string "ef" is concatenated to the string "abcd". This newly created object is assigned to reference variable s (and is not added to the String Literal Pool). At this moment the String object (not the String literal) with the value "abcd" has no longer active references (the only reference variable referring to this object, s, is reassigned to another String object with value "abcdef") and thus is this String object with value "abcd" eligible for GC.
    3/ line3 is completely equivalent with line2 => the String literal "g" is added to the String Literal Pool, a new String object is created by appending "g" to "abcdef", this newly created String object (with value "abcdefg") is assigned to reference variable s and thus the String object with value "abcdef" is eligible for GC.
    4/ line4 is completely equivalent with line2 as well => the String literal "h" is added to the String Literal Pool, a new String object is created by appending "h" to "abcdefg", this newly created String object (with value "abcdefgh") is assigned to reference variable s and thus the String object with value "abcdefg" is eligible for GC.
    5/ On line5 the index of "e" is returned (which is 4) and then a new String object is created which is the substring of "abcdefgh" starting from index 0 (inclusive) to index 4 (exclusive). This newly created String object (with value "abcd") is assigned to reference variable s and thus the String object with value "abcdefgh" is eligible for GC.

    In the OCAJP forum you'll find plenty of topics about strings and the String Literal Pool. If you want to read a bit more about this hard to understand topic, the following topics are definitely worth reading as they offer great explanations with informative code snippets:
  • new String("abc") - one object or two?
  • strings and the string pool
  • What is now right about the String?


  • And finally, although strings and garbage collection can be lots of fun I like to mention this quite important note (from K&B7, page 201)
    K&B7 wrote:Note: Due to the vagaries of the String constant pool, the exam focuses its garbage collection questions on non-String objects, and so our garbage collection discussions apply to only non-String objects too.


    Hope it helps!
    Kind regards,
    Roel
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic