Hi i am working in java and want to know how String objects are created in the String pool
and how they are managed.
So in the following example i am creating two Strings s and s1,so can anyone explain me how many Objects are created in LIne1?Also how many Objects are eligible for garbage collection in Line3?
String s = "x" + "y";//Line 1
String s1 = s;//Line 2
s = null;//Line 3
Only one object is created "xy" . compiler does it for optimization.
No object is eligible for garbage collection.
It would create one object xy in the String constant pool area. As "x"+"y" would be evaluated during compilation. Additionally, garbage collector cannot access String constant pool area.
Reference: https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5
Related
This question already has an answer here:
Garbage collection on intern'd strings, String Pool, and perm-space
(1 answer)
Closed 5 years ago.
How many objects will be eligible for garbage collection after completion of compute method?
I have searched this question and everywhere the answer is 1.
public void compute(Object p)
{
Object a = new Object();
int x = 100;
String str = "abc";
}
But as far as I know, the string constant pool is a part of the heap now in Java 7 and eligible for garbage collection.
According to me, 2 objects are eligible for garbage collection i.e a and str.
It doesn't matter where objects get created.
The only thing that matters is: is the object alive?
In other words: when the last reference to an object goes out of use (or the holder of that reference isn't alive anymore) then the object is eligible for garbage collection.
An object created locally in a method can't be reached any more - it is no longer alive when the method returns. Things would be different for example if that method would add a to some (still live) "global" list for example.
Regarding str, there are multiple misconceptions:
no String object is created: the string literal goes into the constant pool. It would be a different story if you had used new String("abc") for example. In your case: no object, thus no garbage collection for that string.
str is holding a reference. There is no garbage collection for references, just for objects.
String s = "hello";
String literals have references in String Literal Pool and are not eligible of garbage collection, ever. So, after above line even if I say:
s=null;
String object "hello" will still be in heap as I understand. Source: https://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html
Does same holds true for strings inside String array? Suppose we have
String[] arr = {"one","two","three"};
arr=null;
Will the 3 string objects still be on heap referenced from pool? or they will be eligible for garbage collection along with array object.
String literals have references in String Literal Pool and are not eligible of garbage collection, ever.
Actually, that is not strictly correct ... see below.
Will the 3 string objects still be on heap referenced from pool? or they will be eligible for garbage collection along with array object.
They will not be referenced "from the pool". The references in the pool are (in effect) weak references.
They will not be eligible for garbage collection.
What is actually going to happen is that the String objects (in the string pool) that correspond to string literals in the source code will be referenced by the code that uses the literals; i.e. there are hidden references in hidden objects that the JVM knows about. These references are what the JVM uses when you (for example) assign the string literal to something ...
It is those hidden references that mean the weak references in the pool don't break, and the corresponding String objects don't get garbage collected.
Now, if the code that defines the literals was dynamically loaded, and the application manages to unload the code, then the String objects may become unreachable. If that happens, they will eventually be garbage collected,
If jvm creates string pool for memory optimization, then why it creates new Object each time we create string using new keyword even though it exists in string pool?
... why does Java create new Object each time we create a string using the new keyword even though it exists in string pool?
Because you explicitly told it to! The new operator always creates a new object. JLS 15.9.4 says:
"The value of a class instance creation expression is a reference to the newly created object of the specified class. Every time the expression is evaluated, a fresh object is created."
For the record, it is nearly always a mistake to call new String(String) ... but in obscure cases it might be useful. It is conceivable that you might want a string for which equals returns true and == gives false. Calling new String(String) will give you that.
For older versions of Java, the substring, trim and possibly other String methods would give you a string that shared backing storage with the original. Under certain circumstances, this could result in a memory leak. Calling new String(str.trim()) for example would prevent that memory leak, at the cost of creating a fresh copy of the trimmed string. The String(String) constructor guarantees to allocate a fresh backing array as well as giving you a new String object.
This behavior of substring and trim changed in Java 7.
To give primitive style of declaration and for performance designers introduced String literals.
But when you use new keyword, then you are explicitly creating objects on heap not in constant pool.
When the objects created on heap, there is no way to share that memory with each other and they become completely strangers unlike in constant pool.
To break this barrier between heap and constant pool String interning will help you out.
string interning is a method of storing only one copy of each distinct string value, which must be immutable
Remember that constant pool also a small part of heap with some additional benefits where sharing of memory is available.
When you write
String str = new String("mystring");
then it creates a string object in heap just like other object which you create. The string literal "mystring" is stored in the string constant pool.
From the Javadocs:
A pool of strings, initially empty, is maintained privately by the
class String.
When the intern method is invoked, if the pool already contains a
string equal to this String object as determined by the equals(Object)
method, then the string from the pool is returned. Otherwise, this
String object is added to the pool and a reference to this String
object is returned.
It follows that for any two strings s and t, s.intern() == t.intern()
is true if and only if s.equals(t) is true.
To take advantage of string pooling you need to use String#intern instead of new.
Following object will be stored in String pool :
String s = "hello";
And following object will be stored in Heap (not in string pool):
String s = new String ("hello")
To enforce garbage collection!. If you need some String just one time, then there is no point in keeping it in memory (for almost forever. Which is the case with Strings in constant pool). Strings which are not in the constants pool can be GCed like any other object. So, you should only keep frequently used Strings in the constants pool (by using literals or interning them).
Strings created in the form of String literals (String s = "string";) are stored in string pool, but Strings created by invoking String constructor using new (String s = new String("string");, are not stored in string pool.
This question already has answers here:
String pool vs Constant pool
(3 answers)
Closed 8 years ago.
So, I realize the questions I'm about to ask relate to a topic that has been beaten to death time and time again, however, even after reading all of the answers and documentation I could find, I'm still kind of confused about string interning. Perhaps it's due to my lack of understanding for the JVM; perhaps it's due to the changes introduced in Java 7 depreciating many of the aforementioned answers and documentation. Either way, I'm stuck, and I'm hoping someone can help me understand the concept a bit more clearly...
String a = "text";
String b = new String("text");
In the above example, I understand that two String objects will be created. I also understand that there will be only one char array containing the sequence 't', 'e', 'x', and 't' in memory.
However, where in memory are each of the string objects actually stored?
If what I've read I've read correctly: the referent of variable a will be stored in the constant pool whereas the referent of b will be stored in the heap, right?
If that be the case, I'm confused as to how the intern pool maintains interned strings. Does it keep track of the Strings defined in the constant pool and those that have been manually interned (invoked .intern()) from the heap? Does the JVM create the string objects defined in the constant pool and load them into the intern pool? I'm confused as to how it all works...
Again, sorry for asking such confusing/asinine questions, it's just that I'm relatively new to the structure and inner-workings of the JVM and a lot of it has left my head spinning. Thanks!
There's a thing called String Memory Pool in java, when you declare:
String str1="abc";
It goes to that memory pool and not on the heap. But when you write:
String str2=new String("abc");
It creates a full fledged object on the heap, If you again write:
String str3 = "abc";
It won't create any more object on the pool, it will check the pool if this literal already exists it will assign that to it. But writing:
String str4 = new String("abc");
will again create a new object on the heap
Key point is that:
A new object will always be created on the heap as many times as you keep writing:
new String("abc");
But if you keep assigning the Strings directly without using the keyword new, it will just get referenced from the memory pool (or get created if not present in the memory pool)
intern() method finds if the string is present in the memory pool if it is not it adds it to the memory pool and returns a reference to it. so after using this method the String reference of yours is not pointing to any object on the heap, it is pointing to an object in the String Memory Pool (Also, note that the memory pool only contains unique strings).
When you say new String() you get a new Object reference so consider
String a = "text";
String b = new String("text");
System.out.println(a == b);
b = b.intern();
System.out.println(a == b);
Then first a == b will display false because they are different references. If we intern() b by saying b = b.intern() we can then test again and get true. I hope that helps. The above code has worked the same way in Java since version 1.0 (and it still works this way in Java 8 today).
String str1="JAVA";
String str2="JAVA";
String str3=new String("JAVA");
String str4=new String("JAVA").intern();
2 objects will be created. str1 and str2 refer to same object because of String literal pool concept and str3 points to new object because using new operator and str4 points to the same object points by str1 and str2 because intern() method checks into string pool for string having same value.
str1=str2=str3=str4=null;
One object will be eligible for GC. That is the object created through String str3=new String("JAVA"). The first String object is always accessible through reference stored in string literal pool.
Is my explanation correct?
Total Number of String objects created in the process?
Three: The one in the intern pool created via the literal and the two you create via new String.
One object will be eligible for GC.
I count two, and possibly even all three under very special circumstances:
The one you created in this line:
String str3=new String("JAVA");
(since you later set str3 to null).
The one you created temporarily in this line:
String str4=new String("JAVA").intern();
That line creates a new String object, calls intern on it, and then saves a reference to the string from the pool. So in theory, it creates a String object that is immediately available for GC. (The JVM may be smart enough not to do that, but that's the theory.)
Possibly, eventually, under the right conditions, even the string in the intern pool. Contrary to popular belief, strings in the intern pool are available for garbage collection as we can see from the answer to this other question. Just because they're in the permgen (unless you're using Oracle's JVM 7 or later) that doesn't mean they're not GC'd, since the permgen is GC'd too. So the question becomes: When or how is a string literal used in code no longer referenced? I don't know the answer, but I think a reasonable assumption would be: When and if the class using it is unloaded from memory. According to this other answer, that can only happen if both the class and its classloader are unloaded (and may not happen even then). If the class was loaded by the system classloader (the normal case), then presumably it's never unloaded.
So almost certainly just two (#1 and #2 above), but it was fun looking into #3 as well.