aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes String x = Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Java 8 in Action this week in the Java 8 forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "String x = "hi" ;   garbage collected ? " Watch "String x = "hi" ;   garbage collected ? " New topic
Author

String x = "hi" ; garbage collected ?

Rodge Thomas
Ranch Hand

Joined: Jul 25, 2002
Posts: 38
javacaps mock exam 1, #12:
From the following code how many objects are eligible for garbage collection?
String string1 = "Test";
String string2 = "Today";
string1 = null;
string1 = string2;
A) 1
B) 2
C) 3
D) 0
ANSWER: A
------
Shouldn't it be D, since creating strings without using null creates them on the heap, not the stack. Hence, they are ineligible for garbage collection.
Thank you for any replies.
Rodge Thomas
Ranch Hand

Joined: Jul 25, 2002
Posts: 38
So sorry.
I meant to type:
"without using new", not
"without using null"
Anthony Villanueva
Ranch Hand

Joined: Mar 22, 2002
Posts: 1055
Hi Rodge, the pencil and paper icon allows you to edit your posts.
Anyway, Java objects are never placed on the stack.
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056
I thought string literals lived in the string pool and are therefore never garbage-collected.


Ron Newman - SCJP 1.2 (100%, 7 August 2002)
Barkat Mardhani
Ranch Hand

Joined: Aug 05, 2002
Posts: 787

The String class represents character strings. All string literals in Java programs, such as "abc", are implemented as instances of this class.

Above is a quote from String Class description. So
the code in your question is actually creating
new objects of String class and hence candidate
for garbage collection...
Hope this helps...
Thanks
Barkat
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056
Yes, string literals are String objects, but that doesn't mean they are garbage-collected.
[ August 15, 2002: Message edited by: Ron Newman ]
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056
From the Java Language Spec:
3.10.5 String Literals
...
Each string literal is a reference (�4.3) to an instance (�4.3.1, �12.5) of class String (�4.3.3). String objects have a constant value. String literals-or, more generally, strings that are the values of constant expressions (�15.28)-are "interned" so as to share unique instances, using the method String.intern.
That says to me that the interned strings live forever -- they are not GC'd.
[ August 15, 2002: Message edited by: Ron Newman ]
Barkat Mardhani
Ranch Hand

Joined: Aug 05, 2002
Posts: 787
Hi Ron:
Try following program:

You will see that free memory is periodically
restored. That infers that gc has run and released
some memory.
Also more detailed quote from String Class
Description:
The String class represents character strings. All string literals in Java programs, such as "abc", are implemented as instances of this class.
Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. For example:

String str = "abc";

is equivalent to:

char data[] = {'a', 'b', 'c'};
String str = new String(data);

This clear indicates that objects created with:
String str = "abc";
are same as created by
String str = new String("abc");
Therefore, I believe that objects in original
question are also garbage collectables...
Hope this makes it clear..
Thanks
Barkat
[ August 15, 2002: Message edited by: Barkat Mardhani ]
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056
Your program creates a bunch of Strings and StringBuffers every time you call that println() statement. That's what is being garbage-collected, not copies of "abc".
Barkat Mardhani
Ranch Hand

Joined: Aug 05, 2002
Posts: 787
Hi Ron:
You made a good point. But if copies of "abc" are
being piled up, then free memory should have
a net negative trend which I did not observe. Run
following code:

Also, there is no way of knowing for sure that
gc is cleaning up
just the strings created by println or that plus
copies of "abc". Also, creator of question (in
Rodge Thomson's initial note) is assuming that
these are garbage collectable objects. Also as
per String Class description (in note above), a
assertion is being made that two statements have
same effect; meaning both of them will create
same object, hence they should be treated in
same manner by gc.
Has anyone else any more evidence to prove it
one way or other...
Thanks
Barkat
[ August 15, 2002: Message edited by: Barkat Mardhani ]
Valentin Crettaz
Gold Digger
Sheriff

Joined: Aug 26, 2001
Posts: 7610
Just to clear things up (in case they weren't clear before :roll: ):
String literals, that is, strings having a constant value AT COMPILE_TIME are automatically interned (intern() is automatically invoked on them) and are not garbage-collectible until the JVM exits. For instance, the following strings are not garbage-collectible String literals:
String s1 = "some_literal";
String s2 = "" + SOME_PRIMITIVE_CONSTANT;
String s3 = s1 + s2;
(See JLS 3.10.5 String Literals for more examples)
Even though we use the concatenation operator, all of the above Strings are true String literals, because the compiler has all the necessary information to construct them at compile-time.
Side note: I would like to add that there is a bug in the API documentation for class StringBuffer where it is stated that:

String buffers are used by the compiler to implement the binary string concatenation operator +. For example, the code:
String x = "a" + 4 + "c"
is compiled to the equivalent of:
String x = new StringBuffer().append("a").append(4).append("c").toString()
which creates a new string buffer (initially empty), appends the string representation of each operand to the string buffer in turn, and then converts the contents of the string buffer to a string. Overall, this avoids creating many temporary strings.

Unfortunately, the example Sun is taking is very badly chosen since the compiler is able to resolve by itself the literal "a" + 4 + "c" because all elements are constants known at compile-time. If you cut-paste the above code, compile it and decompile it, you'll see that there is not trace whatsoever of StringBuffer within the decompiled byte code. For convenience, I add the decompile code below:

As you can see, the String literal "a4c" has been resolved by the compiler.
Now, I have slightly changed the code to

If we compile and decompile it, we get the following:

The result speaks for itself
Anyway, I have digressed a little bit, but the bottom line is that String literals are never garbage-collected until the JVM is exiting. A good way to see this, would be to look at the C source file which is natively handling String interning. Those sources are not available from Sun, but they are from Kaffe. This is not required for SCJP but it is a very good exercise for anyone who would like to push the challenge a little bit further. For those who are interested, once you have downloaded the kaffe-1.0.7.tgz file, have a look at the C source file named kaffe-1.0.7\kaffe\kaffevm\string.c . Interesting isn't it?


SCJP 5, SCJD, SCBCD, SCWCD, SCDJWS, IBM XML
[Blog] [Blogroll] [My Reviews] My Linked In
Barkat Mardhani
Ranch Hand

Joined: Aug 05, 2002
Posts: 787
Hi Valentin, Ron:
I have following questions:
a. The following statement will create String
literal on the heap or stack?
String S = "abc";
b. Are following references pointing to same object
or two identical but distinct objects:
String S1 = "abc";
String S2 = "abc";
c. How many distinct objects will be created by following:
for (int i=0 ; i<6 ; i++)
String S = "abc";
Thanks for your help to understand this concept
clearly.
Barkat
Valentin Crettaz
Gold Digger
Sheriff

Joined: Aug 26, 2001
Posts: 7610
a. The following statement will create String
literal on the heap or stack?
String S = "abc";

Objects are always created on the heap.
b. Are following references pointing to same object or two identical but distinct objects:
String S1 = "abc";
String S2 = "abc";

S1 and S2 are pointing to the same object on the heap. Try S1 == S2 and you will see.
c. How many distinct objects will be created by following:
for (int i=0 ; i<6 ; i++)
String S = "abc";

1
Barkat Mardhani
Ranch Hand

Joined: Aug 05, 2002
Posts: 787
And one more question:
d. How many distinct objects are now created:
for (int i=0 ; i<6 ; i++)
String S = new String("abc");
Thanks,
Barkat
Valentin Crettaz
Gold Digger
Sheriff

Joined: Aug 26, 2001
Posts: 7610
d. How many distinct objects are now created:
for (int i=0 ; i<6 ; i++)
String S = new String("abc");

6 because the new keyword is used.
[ August 16, 2002: Message edited by: Valentin Crettaz ]
Barkat Mardhani
Ranch Hand

Joined: Aug 05, 2002
Posts: 787
Great, now I am getting the idea. In the final
analysis, will you guys agree that:
1. My code above is NOT creating billion plus
copies of "abc". It is just creating one object
"abc" and pointing to it billion plus times.
2. The object created with :
String S = "abc";
is not garbage collectable even after S points to
another object.
3. Rodge Thomson's observation (above) is correct
that answer to the question should be D not A.
Thanks
Barkat
Valentin Crettaz
Gold Digger
Sheriff

Joined: Aug 26, 2001
Posts: 7610
That's correct
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056
That's right. And someone should tell the author of this mock exam question. Where did you find it?
Rodge Thomas
Ranch Hand

Joined: Jul 25, 2002
Posts: 38
It is from javacaps.com
I emailed them a link to this post.
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Fortunately it's nothing to do with the exam but string literals can be g.c.ed donwloading the class that declared them.
The string objects resulting from compile constant expressions are referred from the constant pool of the class. The constant pool isn't the string pool, but it acts like the symbol table of others languages. If you download the class these references are also cleaned.
The bytecodes ldc #4 and ldc #6, shown above, use these references I'am talking about. I think the bytecode stands for LoaD from the Constant pool.
[ August 17, 2002: Message edited by: Jose Botella ]

SCJP2. Please Indent your code using UBB Code
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056

string literals can be g.c.ed donwloading the class that declared them.

I don't unerstand this -- why would "downloading" a class (from the Internet?) cause anything to be garbage collected?
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Sorry, I didn't mean downloading but unloading. Unloading the class from the VM means that classes can be g.c.ed as well.
Here is the post that shows how. Again this is not tested in the exam. JFYI.
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056
What does it mean to "unload" a class? What is the purpose of doing so?
If I wanted to unload, say, StringBuffer or PrintWriter, how would I do it?
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
You need to load a class in a class loader of your own. And later, because a class loader holds a reference to all the classes that loads, it's necessary to set the class loader to null as well.
There is an example im my previous link.
Again, none of this is exam stuff.
Barkat Mardhani
Ranch Hand

Joined: Aug 05, 2002
Posts: 787
Hi Hose:
If you see my posts (couple of screens above), you
will see that by writing and testing a similar (to
your) program, I came to conclusion that string
literals are g.ced.
Thanks
Barkat
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Barkat, your program doesn't garbage collects string literals because the class that declare them wasn't unloaded. The class still has a reference to the string literals, in its constant pool, when the g.c. runs.
I thought you have agreed with Val in your last post.
Patrick Ansari
Greenhorn

Joined: Feb 23, 2002
Posts: 8
I'm getting false and not true. Am I missing something here?
private void doStuff()
{
String s1 = "abc";
String s2 = "abc";
System.out.println("s1 == s2 : " + s1==s2);
}
Patrick Ansari
Greenhorn

Joined: Feb 23, 2002
Posts: 8
ok interesting - so why does my previous post evaluate to false if this:
System.out.println(s1==s2);
evaluates to true?
Patrick Ansari
Greenhorn

Joined: Feb 23, 2002
Posts: 8
System.out.println("s1 == s2 : " + (s1==s2));
something to do with order precedence? becuase this here works just fine with the parenthesis.
output: s1 == s2 : true
Barkat Mardhani
Ranch Hand

Joined: Aug 05, 2002
Posts: 787
Hi Hose:
I agreed with Val because I am not that experienced and I did not have any way of
knowing which "object" are actually being
cleaned up by GC. Also Val maintained that
my program was not creating billion plus
String literal objects "abc". It was actually
creating one and keep on pointing to it again
and again. And Val said that that single string
literal "abc" is never GCed. I believe what you
are saying is that if you unload the class that
created this particular string literal then it
is candidate for garbage collection.
In posts above, by Patrick, it is evident that
s1 and s2 are point to same object therefore
s1==s2 evaluates to true. But Hose how are you
certain that after unloading corresponding class
the string literal "abc" is actual being GCed. In
other words, is there any way of finding out
which obects are actually GCed?
Thanks
Barkat
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056

Addition has higher precedence than equality, so this parses as

which is obviously false.
See
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/expressions.html
for an operator precedence table.
Patrick Ansari
Greenhorn

Joined: Feb 23, 2002
Posts: 8
Thanks Ron - that's what I thought...
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Barkat,
with java.lang.ref.WeakReference.get() is possible to know when an object is ready/about to be g.c.ed
When the g.c. encounters an object that is referred only by weak references(1) it clears these references. The get method returns now null.
___________
(1) weak or phantom references I think
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056
If someone could explain the difference between Weak and Soft references, I'd greatly appreciate it. I actually asked such a question over in Intermediate but nobody has answered it.
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
I was going to write something. But API explains it better than me. What a relief!
[ August 19, 2002: Message edited by: Jose Botella ]
Ron Newman
Ranch Hand

Joined: Jun 06, 2002
Posts: 1056
I've read both the SoftReference and WeakReference API documents and still don't understand the difference between the two.
Jose Botella
Ranch Hand

Joined: Jul 03, 2001
Posts: 2120
Let me copy because I am a lazy man.

* An object is strongly reachable if it can be reached by some thread without traversing any reference objects. A newly-created object is strongly reachable by the thread that created it.
* An object is softly reachable if it is not strongly reachable but can be reached by traversing a soft reference.
* An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.
* An object is phantom reachable if it is neither strongly, softly, nor weakly reachable, it has been finalized, and some phantom reference refers to it.
* Finally, an object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of the above ways.

Let's suppose an object is pointed by a strong reference and by a weak one. Calling get() on the weakReference will return an strong reference to it. Imagine the object looses its strong reference. You can still access to it through the get method. Nothing happens untill the g.c. runs because of scarcety of memory. When the g.c. encounters an object that isn't reachable via strong references but it is via weak ones, it clears all weak references pointing to it. Also it make the object finalizable. Now the get method will return null.
The object isn't pointed by any weak or strong reference and can be finalized and later g.c.ed
So what? are you asking yourself. Thanks for your patience so far.
Note that the object has gone from an state in which it was strongly (normally) reachable, to an state in which it can be g.c.ed -if the g.c. runs due to memory neeeds, though alternatively it can be used again via the get method -if the g.c. haven't run.
If using strong references, instead of weak, the g.c. could end up in a OutOfMemoryError more easily. With weak references it is allowed to collect more objects, the pointed by weak references.
However WeakRefernces are used for canonicalizing maps as the API for WeakHashMap explains.
The difference with SoftReferences is that the g.c. won't clear the reference to the object and it wont' make finalizable the object as soon as it determines it is softly reachable. The g.c. will only proceed to do that if the there is necessity for more memory than available.
SoftReferences are used to construct caches sensible to (the lack of) memory.
You can read much more on the online chapters of Inside the Java 2 Virtual Machine by Bill Venners
here
It follows a little program:
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: String x = "hi" ; garbage collected ?
 
Similar Threads
GC
how many objects are eligible for garbage collection?
garbage collector
About Garbage Collection!!
how many objects are eligible for garbage collection?