File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes GC question Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "GC question" Watch "GC question" New topic

GC question

Matt Ghiold
Ranch Hand

Joined: Feb 24, 2002
Posts: 213
Hey guys,
I want to throw this out, when questions relate to qc in terms of when will item a be eligible for GC etc.
For example:

Questions, how many Items are eligible for GC after line 3, and 5:
My answer would be 1, 2 (a and b), but depending
on who's mock exam you take, the answer varies.
The rule of thumb I use is when an object becomes null and is no longer referenced it is eligible for GC, now if that object referred to a literal string, it will still be GCed if that object is set to null and no longer referenced anywhere else.
Is this a good rule of thumb?? Because, I find depending on the test, the answer is yes and no.
Please help.

-Matt<br /> SCJP2<br /> SCJD
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
Originally posted by Matt Ghiold:
The rule of thumb I use is when an object becomes null and is no longer referenced it is eligible for GC, now if that object referred to a literal string, it will still be GCed if that object is set to null and no longer referenced anywhere else.

Unfortunately, garbage collection string literals is a fuzzy area. It's true that they can be garbage collected, but this is not generally done. Rather, when a string literal is created, it is created as part of the "literal pool." These strings can be reused as often as need be in order to optimize the code somewhat. Basically, assume that string literals are never garbage collected.
Knowing that, I'd say that the answer to each question is 0. The only object created is a String literal, which is never garbage collected.
Of course, looking at this code, I think the answer to each question would be 0 even if the object created wasn't a String literal but some other normal object, such as a StringBuffer. In each line of the code, there is at least one reference to the object from an active part of the program, so it will never be garbage collected.
Look here to see what's happening (as best I can show with text):

As you can see, at each line, at least one variable references the object, so it would never be eligible for garbage collection.
I hope that helps,

SCJP Tipline, etc.
Matt Ghiold
Ranch Hand

Joined: Feb 24, 2002
Posts: 213
So, you are saying that when you have a literal string a that created a literal string "abc", a will not be garbage collected if it is set to null, because, the string in the literal pool, which always keep a reference to A? That doesnt sound right, to me, in that you created a literal string on the heap, and then your object A on the stack contains a reference to the literal string A = "abc" when initialy created, now when I set A to null, the heap cannot reference the stack to keep it alive ie, "abc" has no idea that string A, is referencing it, but if I interpret what you said correctly, I think thats what you are saying?
Can you elaborate further please.
Rob Ross

Joined: Jan 07, 2002
Posts: 2205
Here's a simplified version of how String literals work in java.
In a source file, when you create a constant, the compiler does something "special" with it when you compile. This happens with any kind of constant by the way...
final int numFingers = 5; //line 1
String redColorName = "Red"; //line 2
int fingerCount = numFingers*2; //line 3
These are examples of constants. In line one, the identifier "numFingers" refers to a constant value.
When you compile this code, the compiler does something like when it converts line 3 to byte code: (again this is simplifed)
load fingerCount with value from integer constant table ID#12345 and multiply by 2.

This integer constant table is part of the .class file for the class that got compiled. Since the final variable can never change, the compiler uses the constant table as a way of storing and referencing the constant value.
Now, String literals work in a similar fashion. The ONLY difference is that a String is an object, whereas an integer is a primitive. So in the String constant table for the .class file, instead of a value like "5", a reference to the constant String object is kept. Line 2 gets compiled to something like this:
load redColorName with value from String object referenced in the String constant table ID#12345

Now, the ClassLoader that loads the .class file containing this String constant table actually creates a new String object, with the value of the literal (in this case "Red"), and stores the reference to this new String object in this String table. Each time you run the application and the .class file is loaded, the ClassLoader initializes the String constant table and makes sure that ID#12345 references a String object with the value "Red". The Value is the actual reference value, which may be interpreted loosely as a memory address, or better yet, a hash code - but it works the same way as a pointer in a language like C or C++.
Anyway, the new String is created on the Heap. ALL objects get created on the heap. But as you can see, a reference to this String object is always accessable via this String contant table. That entry NEVER gets set to null while the class is loaded. When you create your own string objects using this string literal, all you are doing is *copying* the value of the reference in the String constant table.
Ie, if you write in one of your methods.
String anotherString = "Red";
the compiler creates bytecode like I mentioned above:
load anotherString with value from String object referenced in the String constant table ID#12345
If you later set your variable to null:
anotherString = null;
All you have done is clear ONE reference to that STring object. The String object with the value "Red" is still on the heap, and still not eligible for garbage collection, because the entry in the String constant table still contains a reference to it. And it always will while the class is loaded.

That is why String literals are NEVER eligible for garbage collection.
[ March 06, 2002: Message edited by: Rob Ross ]

SCJP 1.4
Dirk Schreckmann

Joined: Dec 10, 2001
Posts: 7023
A quick read of Cup Size and Pass-By-Value Please might help to clear up issues on references & objects.
Good Luck,
-Dirk Schreckmann

[How To Ask Good Questions] [JavaRanch FAQ Wiki] [JavaRanch Radio]
Corey McGlone
Ranch Hand

Joined: Dec 20, 2001
Posts: 3271
As if Rob hadn't cleared this up enough, here's a hefty thread on the subject started by Rob some time ago. Link!
Ahh, yes - everything is so clear now - thanks, Rob.
Jian Yi
Ranch Hand

Joined: Feb 01, 2002
Posts: 127
Hi Rob,
According to your explanation, literals are stored in constant table. So what happens to the code below?

At line 2, does it check if "abc" literal already exists in the constant table?
Thanks a lot,
Rob Ross

Joined: Jan 07, 2002
Posts: 2205
At compile time, bytecode is created that will load both references variables with a copy of the reference to a single String object on the heap that has the character sequence "abc."
That's why (a==b) is true, because they both refer to the same String object.
Vijay Albuquerque
Ranch Hand

Joined: Feb 17, 2002
Posts: 42
Hi Rob,

For the above, would a==b always return true?
Then why are we encouraged to use the equals() method and not ==, to check for string equality?
[ March 07, 2002: Message edited by: Vijay Albuquerque ]

Vijay Albuquerque
SCJP 1.4, SCWCD 1.3
Macon Pegram

Joined: Mar 01, 2002
Posts: 12
It's all about the references...
given the code:

We've already established that "abc" is stored on the heap only once and that variable a refers to the heap memory location of "abc" and that variable b refers to the same heap memory location of "abc" (as a quickie review.. remember variables that are not primative REFER to objects.. they are not the objects themselves).
So with all that in mind == will compare the value of the references, not the actual value contained within those references.
We use the equals() method to do a character by character comparison of two strings. To think of it differently. Look at the following:

In the code fragment above if statement // 3 will print out "b == c" because in line //1 we copy the REFERENCE of b into c.
When if statement // 4 runs however "b != d" will be printed despite the fact that the value refered to by each of the variables equivalent. The REFERENCE to those two values is different. b refers to an instance of Integer on the heap that contains the value 5, while d refers to a DIFFERENT instance of Integer on the heap that also happens to contain the value 5. To make this work correctly we should change the if statement in line 4 as follows:

This would work because it's comparing actual values as opposed to references, and as a result would output "b == d".
I agree. Here's the link:
subject: GC question
It's not a secret anymore!