Confusion on string immutability - java

I have following code:-
public class StaticImplementer {
private static String str= "ABC";
public static void main(String args[]) {
str = str + "XYZ";
}
}
Questions:-
Here String str is static, then where this object will be stored in memory?
Since String is immutable, where the object for "XYZ" will be stored?
Where will be final object will be Stored?
And how will garbage collection will be done?

1) Here String str is static, then where this object will be stored in
memory?
Those literals will be stored in the String pool memory, no matter if the variable is declared as static or not.
More info here: Where does Java's String constant pool live, the heap or the stack?
2) Since String is immutable, where the object for "XYZ" will be stored?
Similar to the first answer: a literal will be stored in the pool memory.
Immutability just allows the concept of shared pool memory.
3) Where will be final object will be Stored?
According to the Java specification, concatenation of literals will end up to a literal too (since known at compilation time), stored in the pool memory.
Excerpt:
"This is a " + // actually a string-valued constant expression,
"two-line string" // formed from two string literals
4) And how will garbage collection will be done?
As essence of the pool memory, they won't be garbage collected by default.
Indeed, if garbage collected immediately, the "shared" concept of the pool would fail.

Here String str is static, then where this object will be stored in
memory?
String str is not an object, it's a reference to an object. "ABC", "XYZ" & "ABCXYZ" are three distinct String objects. Thus, str points to a string. You can change what it points to, but not that which it points at.
Since String is immutable, where the object for "XYZ" will be stored?
As explained in above & also by Mik378, "XYZ" is just a String object which gets saved in the String pool memory and the reference to this memory is returned when "XYZ" is declared or assigned to any other object.
Where will be final object will be Stored?
The final object, "ABCXYZ" will also get saved to the pool memory and the reference will be returned to the object when the operation is assigned to any variable.
And how will garbage collection will be done?
String literals are interned. As of Java 7, the HotSpot JVM puts interned Strings in the heap, not permgen. In earlier versions of Java, JVM placed interned Strings in permgen. However, Strings in permgen were garbage collected. Apparently, Class objects in permgen are also collectable, so everything in permgen is collectable, though permgen collection might not be enabled by default in some old JVMs.
String literals, being interned, would be a reference held by the declaring Class object to the String object in the intern pool. So the interned literal String would only be collected if the Class object that referred to it were also collected.
Shishir

Related

How String pool manages references if we change string value?

If we have a String s = "Hello" It will create string "Hello" in string pool and some reference is pointing to string s what if I change s="World" .In string pool it will create new String "World" and now my reference is pointing to World. What will happen to "Hello" String?
From the documentation of String:
... String objects are immutable ...
String-constants known at compile-time are also treated specially. They are stored in a constant pool. All "equal" compile-time String-constant reference the same String-object. This is the reason why
String s1 = "Hello";
String s2 = "Hello";
System.out.println(s1 == s2);
will print true. There are some other interesting examples. I wrote an Ideone example a while back that demonstrates some of those interesting cases.
When one re-assings a value to some non-primitive type variable s, the old object still exists on the heap (as long as the Garbage Collector does not deem it eligible for collection). What is changed is where the variable s is referencing. In the case presented, a second String-constant is created at compile-time and s then references the second constant.
String objects are immutable, so what happens with your second assignment is only an object reference update.
String literal objects (like "Hello" and "World") will be referenced from Java's String pool (they are interned). As this counts as a reference, the "Hello" object will not be garbage collected after your reassignment. That will only happen if the code itself becomes unreachable (e.g. if the entire class was loaded dynamically and its class loader becomes now unreachable).

String pool - do String always exist in constant pool?

When string is created by using literal, it gets stored in pool. But when new operator is used to create String object, it stores the object in Heap.
But is the object in heap just a pointer to literal stored in pool or is it a simple String object stored in heap which is eligible for GC?
Terminology:
The Constant Pool is an area in (each) .class file that contains various constants, including strings. No runtime objects exist in the constant pool. It is a region of a file.
The String Pool is a runtime data structure used by the JVM to manage certain kinds of strings. (Specifically, String objects that correspond to literals, and String objects added to the pool by String::intern().)
Your question is actually talking about the String Pool, not the Constant Pool.
To answer your questions:
String pool - do String always exist in constant pool?
No. A string object created using new String() doesn't exist in either the string pool or the constant pool.
When string is created by using literal, it gets stored in pool.
The string (already!) exists the constant pool and gets created as a Java String object in the string pool. (The actual creation can be at class load time, or when the literal is first used. This depends on the Java implementation.)
But when new operator is used to create String object, it stores the object in Heap.
Yes. But the string pool is also part of the Heap. Like I said, it is a data structure, not a region of storage.
(In the old days, the string pool lived in a special heap called the PermGen heap. But PermGen was replaced with something else (MetaSpace), and the string pool doesn't use either ... anymore.
But is the object in heap just a pointer to literal stored in pool or is it a simple String object stored in heap which is eligible for GC?
This is really confused.
All strings are represented as String objects in the (a) heap. That includes strings in the string pool. Even when the string pool was in PermGen.
All String objects that are unreachable are eligible for garbage collection. Even for strings in the string pool. Even for String objects that represent string literals.
But ... wait ... so can string literals be garbage collected?
Yes!! If a String object that represents a string literal becomes unreachable at runtime it is eligible for garbage collection, just like any other String object.
A string literal can become unreachable if the code object(s) that use the literal become unreachable. It can happen, when a classloader becomes unreachable.
And yes, PermGen was garbage collected. At least since JDK 1.2. (IIRC Java 1.0 and maybe 1.1 didn't implement GC for the PermGen heap. But that was fixed a long time ago.)

Immutability of String in JAVA

Consider the code :
public class Stringer {
public static void main(String[] args) {
String s1 = "SomeLine";
System.out.println(s1); // prints SomeLine
s1 = "AnotherLine";
System.out.println(s1); // prints AnotherLine
}
}
When I change s1 from SomeLine to AnotherLine , since Strings are Immutable , does this mean that SomeLine is lost and is eligible for GC ?
Much appreciated
When I change s1 from SomeLine to AnotherLine, since Strings are
Immutable, does this mean that SomeLine is lost and is eligible for
GC?
The fact that String is immutable is irrelevant to your question. The fact that you are reassigning the variable and therefore losing the other reference is what determines if the object is a candidate for GC or not.
To answer the question, it would be if it wasn't a String literal.
Moreover, a string literal always refers to the same instance of class
String. This is because 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 String object won't be garbage collected because the ClassLoader and the corresponding class have a reference to it.
Related reading:
What is the difference between "text" and new String("text")?
Yes you're right, it does become eligible for garbage collection. This is because you are no longer referencing the original string with your variable.
Here is a related question on SO:
Aren't String objects in Java immutable?
It is not that trivial when talking about Strings in Java. Even if the String is interned it can still be garbage collected. In java 6, even if it is allocated in the permgen, it can be garbage collected, in Java 7 they are allocated on the Heap and are still eligible for GC.
Usually interned Strings are not eligible for garbage collection because the class has a reference to it. But what if that class was loaded dynamically (Class.forName)? It could easily be the case when that Class could be unloaded, thus an interned string could be reclaimed by GC.
See an example here that shows that interned strings could be garbage collected.

Garbage collection of String literals

I am reading about Garbage collection and i am getting confusing search results when i search for String literal garbage collections.
I need clarification on following points:
If a string is defined as literal at compile time [e.g: String str = "java"] then will it be garbage collected?
If use intern method [e.g: String str = new String("java").intern()] then will it be garbage collected? Also will it be treated differently from String literal in point 1.
Some places it is mentioned that literals will be garbage collected only when String class will be unloaded? Does it make sense because I don't think String class will ever be unloaded.
If a string is defined as literal at compile time [e.g: String str = "java";] then will it be garbage collected?
Probably not. The code objects will contain one or more references to the String objects that represent the literals. So as long as the code objects are reachable, the String objects will be to.
It is possible for code objects to become unreachable, but only if they were dynamically loaded ... and their classloader is destroyed.
If I use the intern method [e.g: String str = new String("java").intern()] then will it be garbage collected?
The object returned by the intern call will be the same object that represents the "java" string literal. (The "java" literal is interned at class loading time. When you then intern the newly constructed String object in your code snippet, it will lookup and return the previously interned "java" string.)
However, interned strings that are not identical with string literals can be garbage collected once they become unreachable. The PermGen space is garbage collected on all recent HotSpot JVMs. (Prior to Java 8 ... which drops PermGen entirely.)
Also will it be treated differently from string literal in point 1.
No ... because it is the same object as the string literal.
And indeed, once you understand what is going on, it is clear that string literals are not treated specially either. It is just an application of the "reachability" rule ...
Some places it is mentioned that literals will be garbage collected only when String class will be unloaded? Does it make sense because I don't think the String class will ever be unloaded.
You are right. It doesn't make sense. The sources that said that are incorrect. (It would be helpful if you posted a URL so that we can read what they are saying for ourselves ...)
Under normal circumstances, string literals and classes are all allocated into the JVM's permanent generation ("PermGen"), and usually won't ever be collected. Strings that are interned (e.g. mystring.intern()) are stored in a memory pool owned by the String class in permgen, and it was once the case that aggressive interning could cause a space leak because the string pool itself held a reference to every string, even if no other references existed. Apparently this is no longer true, at least as of JDK 1.6 (see, e.g., here).
For more on permgen, this is a decent overview of the topic. (Note: that link goes to a blog associated with a product. I don't have any association with the blog, the company, or the product, but the blog entry is useful and doesn't have much to do with the product.)
The literal string will remain in memory as long as the program is in memory.
str will be garbage collected, but the literal it is created from will not.
That makes perfect sense, since the string class is unloaded when the program is unloaded.
intern() method checks the availability of the object in String pool. If the object/literal is available then reference of it will be returned. If the literal is not there in the pool then object is loaded in the perm area (String pool) and then reference to it will be return. We have to use intern() method judiciously.

Garbage collection and Strings

I have some doubts regarding Strings
Are they live on Heap or String pool?
And if on Heap then they will be garbage collected, if they are not reachable by any live thread.
And if on String pool then how they will be deleted or removed because as we know Garbage Collection happens only on heap.
String s = new String("abc");
the string object referred by s will be on heap and the string literal "abc" will be in string pool. The objects in the string pool will not be garbage collected. They are there to be reused during the lifetime of the program, to improve the performance.
They are all stored in the heap, but intern()ed strings (including string literals in the source) are referenced from a pool in the String class.
If they appear as literals in the source code, including constant string expressions (e.g. "a" + "b") then they will also be referenced from the Class the appear in, which usually means they will last as long as the process runs.
Edit:
When you call intern() on a string in your code it is also added to this pool, but because it uses weak references the string can still be garbage collected if it is no longer in use.
See also:
interned Strings : Java Glossary
Quote from that article:
The collection of Strings registered in this HashMap is sometimes called the String pool. However, they are ordinary Objects and live on the heap just like any other (perhaps in an optimised way since interned Strings tend to be long lived).
String Alex goes into the literal pool, stays there as long as the process runs (or the web application remains loaded.) as told by finnw and is never garbage collected. String name2 doesn't allocate memory for "Alex" and reuses it from the literal pool.
PS: Literal pool is on the heap as well.
For string John two objects are created with reference name3 and name4 which are garbage collectible.
String name = "Alex";
String name2 = "Alex";
String name3 = new String("John");
String name4 = new String("John");

Categories