How String pool manages references if we change string value? - java

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).

Related

Why intern method in String if object is created with new operator?

I have seen many questions regarding object created using string literal and new keyword like:
How many String objects using new operator
But it doesn't clarify my doubts.
Case 1: String object using string literal.
It creates one object in string constant pool if,it is not present otherwise, return the reference of this object.This object is implicitly interned.
Case 2:String object using new().
it creates 2 objects,one in string constant pool and another one in heap area.Reference variable refer to the heap area object.For this object we need to call intern method to put this object into string constant pool explicitly.
My question is if new() already creates one object in string constant pool then, what is use of calling intern method on the object which is there in heap area?
Case 2:String object using new(). it creates 2 objects,one in string constant pool and another one in heap area.
Only if you create a new String object by passing it a string literal, like this:
String s = new String("hello");
The literal "hello" will cause an object in the string constant pool to be created. The new String will create a new String object on the heap, with a copy of the content of the object for the literal.
You should never create String object like that, because it's unnecessary and inefficient.
There are however other reasons why you would want to do new String(...), when the value that you pass to the constructor is not a string literal. For example, the value is data read from a file.
Case 1: String object using string literal. It creates one object in string constant pool
Correct.
if,it is not present
Wrong. It is present.
otherwise, return the reference of this object.
It always return the reference of the object. No 'otherwise' about it.
This object is implicitly interned.
Not really. It is already interned, because it is a string literal. The compiler and class loader see to that. Not thenew operator.
Case 2:String object using new(). it creates 2 objects,one in string constant pool
Not really. It was already there: see above.
and another one in heap area.
Correct.
Reference variable refer to the heap area object.For this object we need to call intern method to put this object into string constant pool explicitly.
Correct.
My question is if new() already creates one object in string constant pool
It doesn't. See above.

Confusion on string immutability

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

String with new keyword and direct assignment in java [duplicate]

This question already has answers here:
What is the difference between "text" and new String("text")?
(13 answers)
Closed 2 years ago.
String s="hi";
String s1=new String("hi");
In memory perspective, where are s and s1 stored? whether it is in heap memory or stack.
And s points "hi" and s1 points to memory location of where hi exists?
Please help?
Consider following
String s = "hi";
String s1 = new String("hi");
variable s will refer to the string literal hi that is referenced from String constant pool and if there are some more variables like s2 = "hi", then s and s2 will refer to same object.
String s1 = new String("hi");
This will create a new String at runtime.
In first case ,all the strnig literals are created when class is loaded in JVM
In seconds case, string objects are created when new String() is executed.
You can find a good tutorial about string constant pool at following link
http://www.thejavageek.com/2013/06/19/the-string-constant-pool/
String s="hi";
This statements creates the String object containing "hi" on the String pool.
String s1=new String("hi");
This statement creates a String object containing "hi" on the heap memory and a copy of it on StringPool (if "Hi" is not contained in stringPool).But here, S will point to the object on heap.
At class loading time, all String literals will be placed in pool. When you use new String("hi") an object will be created on heap. s and s1 are reference variables , it should reside in the method call stack ! The string literal "hi" will be handled by the JVM, by creating a String object on the heap, and having a reference to it from the String pool. The new operator merely takes the string object, whose reference is passed in the constructor, and create a new object. It just so happens that the string being passed to the constructor is a literal.
"hi" is a String literal. This gets created once in the String Constant Pool. In Java 7 that's in the Heap with other objects, but prior to that it was created in the Perm-Gen
String s = "hi";
String s1 = new String("hi");
new String("hi") creates a new String object on the heap, separate from the existing one.
s and s1 are references to the two separate objects. References themselves actually live on the stack, even though they point to objects in the heap.
s and s1 are just references to the strings, therefore they will be stored on the stack, unlike the string instances that are referenced by s and s1. In this case the value that s refers to will be put in the string pool whereas the value refered by s1 won't. Why? because the constructor of a string has been used to make that string. Only literals are pooled, and even if you chose those literals to be concatenations of other literals ( for example, if you have made String s2 = "h" + "i" then s and s2 would point to the same instance of a string that was stored in the string pool).
This leads to a little trap though: because pooled strings point to the same object it is tempting to use == operator instead of equals method to compare strings, which is just dangerous, because there are scenarios where == is the same as equals() but there are a lot more where == will have a different result than the equals() method.
Above answers are correct but shouldn't you use String *s1 = new String("hi") in place ofString s1 = new String("hi") ,as call to new will be returning a pointer to the string object.
I am fairly new to C++. Excuse me, if I am wrong.
PS: I am using the gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC).
According to me when we create String using literal like String s="hello"
s object will reference the String "hello" that is stored in the String Constant pool.
If we will create the new String using New keyword like String s = new String("hello") then in this case two object is created. object s referenced the another object that is stored in the normal heap area and this object will referenced the String Hello that is stored in the String constant pool.
For more details please follow the link:-http://www.javatpoint.com/java-string

Immutable strings in java?

String s = "java";
s.substring(1); // ava
Considering the immutability of strings, compiler doesnot modify 's' but creates a new object or you can say that there is space for 'java' as well as 'ava' in memory..
What happens to this 'ava', as nothing is pointing to it or it's not being referenced by anything..
One more question... If i would have written String s = new String("java"); // 'java' is not in string literal pool....
The 'ava' would be in the string literal pool then or not ?
What happens to this 'ava', as nothing is pointing to it or it's not being referenced by anything..
The newly constructed String object immediately becomes eligible for garbage collection.
As to your second question, I don't think there's any difference between the following two expressions as far as the string literal pool is concerned:
String s = "java";
String s = new String("java");
In both cases, the literal "java" would be in the pool. (But in the second case, s would not refer to the "java" string that's in the pool, but to a different String that also has the characters "java".)
1) What happens to this 'ava', as nothing is pointing to it or it's not being referenced by anything..
As you have not assigned 'ava' to any object means 'ava' is not being pointed by any object so it would be eligible for garbage collection.
2) The 'ava' would be in the string literal pool then or not ?
No it would be in string literal pool.
s.substring(1) creates a new String pointing to the underlying char array of s. The important thing to realise here is that the char array is shared between these two objects. If you use the String(String) constructor a new char array is created containing the referenced characters.
If you throw away the reference to s, if you have a reference to the result of the substring() operation then you have a reference to the full underlying char array.
In your example you're not storing a reference to the newly created String. So that will be garbage-collected very quickly. The underlying array is still referenced by s, however.

Strings of Same Value in Java?

a quick and confusing question. If Class A and Class B have this inside them:-
String name="SomeName";
and both classes are instantiated, is it true that both instances refer to same memory location of variable "name" say when we do this objA.name or objB.name ? which has value "SomeName" and since String is immutable, several instances of both classes of same JVM use the same variable repeatedly? I read somewhere online that, unless there is
String example=new String("something");
is used, the former declaration always creates one copy and it is used until all its applications are terminated for reclaiming memory.
Note: I see several answers, which one do I count on, can someone conclude. Thank you all for your effort, appreciate it.
Yes, if you create two strings like:
String a = "Hello";
String b = "Hello";
They will be the exact same object. You can test it yourself by doing
System.out.println(a == b);
If they are the same object, then their internal reference to the character array will be exactly the same.
Now, if you did String c = "Hell" + "o";, it would not have the same reference since it would have been (internally) built using StringBuilder.
There is a lot of good information here.
The relevant sections has (Note: The following is copied from that web site):
As mentioned, there are two ways to construct a string: implicit construction by assigning a String literal or explicitly creating a String object via the new operator and constructor. For example,
String s1 = "Hello"; // String literal
String s2 = "Hello"; // String literal
String s3 = s1; // same reference
String s4 = new String("Hello"); // String object
String s5 = new String("Hello"); // String object
Java has designed a special mechanism for keeping the String literals - in a so-called string common pool. If two String literals have the same contents, they will share the same storage locations inside the common pool. This approach is adopted to conserve storage for frequently-used strings. On the other hands, String object created via the new operator are kept in the heap. Each String object in the heap has its own storage just like any other object. There is no sharing of storage in heap even if two String objects have the same contents.
You can use the method equals() of the String class to compare the contents of two Strings. You can use the relational equality operator '==' to compare the references (or pointers) of two objects. Study the following codes:
s1 == s1; // true, same pointer
s1 == s2; // true, s1 and s1 share storage in common pool
s1 == s3; // true, s3 is assigned same pointer as s1
s1.equals(s3); // true, same contents
s1 == s4; // false, different pointers
s1.equals(s4); // true, same contents
s4 == s5; // false, different pointers in heap
s4.equals(s5); // true, same contents
Edit to add: Run this SSCE to test reference equality between two constant strings in to different classes:
class T {
String string = "Hello";
public static void main(String args[]) {
T t = new T();
T2 t2 = new T2();
System.out.println(t.string == t2.string);
}
}
class T2 {
String string = "Hello";
}
prints out true.
If "something" is literally hard-coded into your source code, then the two variables will point to the same in-memory String object.
Per the Java spec, a string literal (one that's defined as a literal in the byte codes) is "interned", so that any reference to that literal will obtain the exact same pointer, even if the reference is to an identical literal in an entirely separate class.
A string constructed at runtime (eg, "abc" + "xyz" or new String("abc")) will not be interned, and so the pointer will generally be unique. (But note that an optimizing compiler may combine "abc" + "xyz" into the single literal "abcxyz", resulting in an interned value.)
the former declaration always creates one copy and it is used until all its applications are terminated for reclaiming memory.
Strings, like other object are reclaimed when a GC is performed and there is no strong reference to it. Even intern'ed Strings can be cleaned up when they are no longer used.
I would add one more detail to all the solutions above. String interning is just an optimization of Java/C# compiler. It's not good to rely on it as it can be turned off in both cases.
It may also behave differently in different compilers/VM's implementations

Categories