When will a string be garbage collected in java
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 literalA 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.)
Garbage collection of String literals
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 theString
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 ...)
How String object is garbage collected in java?
Whenever you call new
in JAVA it create an object in heap but in case of String literals, it will go into the String Constant Pool.
Sample code:
String value = new String("ABC");
value = "xyz";
Now in the above sample code "ABC" and "xyz" string literals will go to the String Constant Pool and will not be garbage collected but finally value
is referring to "xyz" from the String Constant Pool.
So basically there are 3 objects, 2 in the String Constant Pool and 1 in the heap.
at which point previously created String object will be garbage collected?
The object is created by new
will be garbage collected once its scope/life is finished or there is no reference to access it. It's applicable similarly for all the objects including String as well.
Since the value
reference will be pointed to the existing object with the value "xyz" within the string constant poll in the next line, so that previously created object using new
in the heap is eligible for garbage collection but not "ABC" string literal that is still in the string constant pool.
Try to visualize it.
Read more...
String Pool - String Object - Garbage Collection
String s1 = "abc"; // s1 points to "abc"
Here, "abc" will be added to the String Constants Pool and will usually not be GCed. Any string literal (within double quotes) will usually not be GCed.
String s1 = new String("abc");
The above line creates 2 Strings. "abc" will be added to the String constants pool (assuming it is not present there already) and another String with value "abc" will on the heap. The String object present on the heap can be GCed once it becomes unreachable (i.e, there are no references to it)
Related Topics
Adding Header for Httpurlconnection
Can't Compile Project When I'm Using Lombok Under Intellij Idea
Using Pairs or 2-Tuples in Java
String Concatenation in Java - When to Use +, Stringbuilder and Concat
Convert Latitude/Longitude Point to a Pixels (X,Y) on Mercator Projection
How Does Auto Boxing/Unboxing Work in Java
Java Random Always Returns the Same Number When I Set the Seed
How to Compare Two Dates Without the Time Portion
Simple Popup Java Form with at Least Two Fields
Why Is the Clone() Method Protected in Java.Lang.Object
Abstracttablemodel Gui Display Issue
Any Way to Invoke a Private Method
Handling Exceptions from Java Executorservice Tasks
Can Java 8 Code Be Compiled to Run on Java 7 Jvm
How to Escape Special HTML Characters in Jsp