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?
From Java 7 onwards, the Java String Pool is stored in the Heap space, which is garbage collected by the JVM.
As long as an object is being referenced, the JVM considers it alive. Once an object is no longer referenced and therefore is not reachable by the application code, the garbage collector removes it and reclaims the unused memory.
When a JVM runs out of space in the storage heap and is unable to allocate any more objects (an allocation failure), a garbage collection is triggered. The Garbage Collector cleans up objects in the storage heap that are no longer being referenced by applications and frees some of the space.
Two way can make this happened: 1. Explicitly set the reference variable that refers to the object to null. 2. Reassign the reference variable that points to the object to refer to other object.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With