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,
Related
In Java, when an object has got no live reference, it is eligible for garbage collection. Now in case of a string, this is not the case because the string will go into the string pool and JVM will keep the object alive for re-use.
So that means a string once created will 'never' be garbage collected?
Now in case of a string, this is not the case because string will go into the string pool and JVM will keep the object alive for reuse. So that means a string once created will 'never' be garbage collected?
First, it is only string literals (see notes) that get automatically interned / added to the string pool. String objects that are created by an application at runtime are not interned ... unless your application explicitly calls String.intern().
Second, in fact the rules for garbage collecting objects in the string pool are the same as for other String objects: indeed all objects. They will be garbage collected if the GC finds them to be unreachable.
In practice, the String objects that correspond to string literals typically do not become candidates for garbage collection. This is because there is an implicit reference to the String object in the code of every method that uses the literal. This means that the String is reachable for as long as the method could be executed.
However, this is not always the case. If a string literal was defined in a class that was dynamically loaded (e.g. using Class.forName(...)), then it is possible to arrange that the class is unloaded. If that happens, then the String object corresponding to the literal may then be unreachable, and may ultimately be GC'ed.
See also: When and how are classes garbage collected in Java?
Notes:
A string literal (JLS 3.10.5) is a string that appears in Java source code; e.g.
"abc" // string literal
new String(...) // not a string literal
A string produced by evaluation of (compile-time) constant expression (JLS 15.28) may also be interned.
"abc" + 123 // this is a constant expression
Strictly speaking, not all String literals are interned:
If a String literal only appears in the source code as a sub-expression of a constant expression, then the literal may not appear in the ".class" file in any form. Such a literal won't be interned because it won't exist at runtime.
In Java 9+, string concatenations involving literals and values that are not compile time constants may be handled differently. Now, at the option of the bytecode compiler, a string concatenation like the following:
int x = 42; // not a compile time constant
String s = "prefix " + x + " suffix";
may result in a string constant like the following being interned:
"prefix \1 suffix"
At runtime, the above string constant is used as the "recipe" for generating a dynamic concatenation method. The original string literals (i.e. "prefix " and " suffix") would not turn into interned string objects.
Kudos to #Holger for pointing this out. More details are in JEP 280 and the javadoc for StringConcatFactory.
Prior to Java 7, the string pool was in PermGen. For some versions of Java, garbage collection of PermGen was not enabled by default if you selected the CMS collector. But CMS was never the default collector AND there was a flag to enable PermGen collection by CMS. (And nobody should be developing code for Java 6 and earlier anymore.)
You are correct; strings in the intern pool will never be GC'd.
However, most strings on not interned.
String literals are interned, and strings passed to String.intern() are interned, but all other strings are not interned and can be GC'd normally.
String objects which are in the string pool will not be garbage collected. Other String objects will be garbage collected if you don't have reference to it in your program execution.
You may ask which string objects goes to string pool.Objects in the string pool are either:
Compile time literals (e.g.String s1 = "123";)
Interned String objects in the runtime (e.g. String s2 = new String("test").intern();)
Both s1 and s2 reference a string object in the string pool.
Any objects which are created at run time and not interned will act as a normal object and reside in heap memory. These objects can be garbage collected.
An example of this would be: String s3 = s1 + s2;
Here, s3 references a string object which resides in heap memory alongside other objects (not in the String pool).
Before Java 7 the string pool resided in Permanent Generation space. So string literals were never garbage collected (which also led to out of memory issues many a times)
After Java 7, string pool is placed in heap space, which is garbage collected by the JVM. It also reduces the chances of getting Out of memory issues in JVM.
As every java developers know java Objects will be garbage collected when no longer in use.
I want to know how JVM identify which object have to pick for garbage collection.
(say eg..If I have 10 objects. out of 10 if 2 objects are garbage collected how jvm finds that two object).
JVM uses "mark and sweep" algorithm(If im right).
1)For example i providing string object scenarios below
class Sample{
public static void main(Strings args[]){
String s1=new String("10");
String s2=new String("20");
String s3=new String("30");
String s4=new String("40");
String s5=new String("50");
String s6=new String("60");
String s7=new String("70");
s1=null; //now s1 is eligible for gc collection
s2=null; //now s2 is eligible for collection
}
}
//now s1 & s2 are eligible for gc collection.If i expicitly made to null references(s1,s2) become null but what happens to the memory allocated on heap? will it be freedup?
Actually nothing happens. The memory used by s1 and s2 will be reused only when GC starts working and this will only happen when JVM decides and it may never happen. In your case GC will hardly ever start.
It's covered fairly succinctly here: http://www.brpreiss.com/books/opus5/html/page424.html
The mark-and-sweep algorithm is called a tracing garbage collector
because is traces out the entire collection of objects that are
directly or indirectly accessible by the program.
The objects that a program can access directly are those objects which
are referenced by local variables on the processor stack as well as by
any static variables that refer to objects. In the context of garbage
collection, these variables are called the roots . An object is
indirectly accessible if it is referenced by a field in some other
(directly or indirectly) accessible object.
So when you do s1=null; you are disconnecting the root, and the corresponding instance becomes eligible for collection.
The actual "collection" (freeing of the heap) occurs when the GC actually executes. As to exactly when this occurs there is not a one-size-fits-all answer to that. See What the frequency of the Garbage Collection in Java?
Assigning null to any reference doesn't free up the memory. It only makes the reference available to remove using garbage collector. Means now this reference allocated memory can be free when garbage collector will run.
If any live thread can't access the object by any means then that object becomes eligible for garbage collection. But there is no guarantee of GC to run as it depends upon JVM internal logic and algorithm.
Generally it happens when JVM thinks that its time to clear up some memory usage.
In your case s1 and s2 are eligible to be GCed but we can't say when it will happen.
An Object becomes eligible for Garbage collection or GC if its not reachable from any live threads or any static references
SEE HERE
Java objects are eligible for garbage collection when the reference count of that object is 0. Reference count being 0 indicates that "that particular object is not referenced by any variable, hence it can not be used anymore". Garbage collector in the first pass mark all such objects whose reference count is 0 and in the second pass it sweeps all the marked object. Hence it is mark and sweep algorithm.
will it be freedup?
It depends on the garbage collector, when the garbage collector re-run after you made the s1 and s2 null, then they will be eligible for garbage collected. But, making reference null won't immediately release the object from the memory
In Java, when an object has got no live reference, it is eligible for garbage collection. Now in case of a string, this is not the case because the string will go into the string pool and JVM will keep the object alive for re-use.
So that means a string once created will 'never' be garbage collected?
Now in case of a string, this is not the case because string will go into the string pool and JVM will keep the object alive for reuse. So that means a string once created will 'never' be garbage collected?
First, it is only string literals (see notes) that get automatically interned / added to the string pool. String objects that are created by an application at runtime are not interned ... unless your application explicitly calls String.intern().
Second, in fact the rules for garbage collecting objects in the string pool are the same as for other String objects: indeed all objects. They will be garbage collected if the GC finds them to be unreachable.
In practice, the String objects that correspond to string literals typically do not become candidates for garbage collection. This is because there is an implicit reference to the String object in the code of every method that uses the literal. This means that the String is reachable for as long as the method could be executed.
However, this is not always the case. If a string literal was defined in a class that was dynamically loaded (e.g. using Class.forName(...)), then it is possible to arrange that the class is unloaded. If that happens, then the String object corresponding to the literal may then be unreachable, and may ultimately be GC'ed.
See also: When and how are classes garbage collected in Java?
Notes:
A string literal (JLS 3.10.5) is a string that appears in Java source code; e.g.
"abc" // string literal
new String(...) // not a string literal
A string produced by evaluation of (compile-time) constant expression (JLS 15.28) may also be interned.
"abc" + 123 // this is a constant expression
Strictly speaking, not all String literals are interned:
If a String literal only appears in the source code as a sub-expression of a constant expression, then the literal may not appear in the ".class" file in any form. Such a literal won't be interned because it won't exist at runtime.
In Java 9+, string concatenations involving literals and values that are not compile time constants may be handled differently. Now, at the option of the bytecode compiler, a string concatenation like the following:
int x = 42; // not a compile time constant
String s = "prefix " + x + " suffix";
may result in a string constant like the following being interned:
"prefix \1 suffix"
At runtime, the above string constant is used as the "recipe" for generating a dynamic concatenation method. The original string literals (i.e. "prefix " and " suffix") would not turn into interned string objects.
Kudos to #Holger for pointing this out. More details are in JEP 280 and the javadoc for StringConcatFactory.
Prior to Java 7, the string pool was in PermGen. For some versions of Java, garbage collection of PermGen was not enabled by default if you selected the CMS collector. But CMS was never the default collector AND there was a flag to enable PermGen collection by CMS. (And nobody should be developing code for Java 6 and earlier anymore.)
You are correct; strings in the intern pool will never be GC'd.
However, most strings on not interned.
String literals are interned, and strings passed to String.intern() are interned, but all other strings are not interned and can be GC'd normally.
String objects which are in the string pool will not be garbage collected. Other String objects will be garbage collected if you don't have reference to it in your program execution.
You may ask which string objects goes to string pool.Objects in the string pool are either:
Compile time literals (e.g.String s1 = "123";)
Interned String objects in the runtime (e.g. String s2 = new String("test").intern();)
Both s1 and s2 reference a string object in the string pool.
Any objects which are created at run time and not interned will act as a normal object and reside in heap memory. These objects can be garbage collected.
An example of this would be: String s3 = s1 + s2;
Here, s3 references a string object which resides in heap memory alongside other objects (not in the String pool).
Before Java 7 the string pool resided in Permanent Generation space. So string literals were never garbage collected (which also led to out of memory issues many a times)
After Java 7, string pool is placed in heap space, which is garbage collected by the JVM. It also reduces the chances of getting Out of memory issues in JVM.
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.
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.