When will a string be garbage collected in java

35,654

Solution 1

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:

  1. 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
    
  2. A string produced by evaluation of (compile-time) constant expression (JLS 15.28) may also be interned.

       "abc" + 123      // this is a constant expression
    
  3. 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.

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

Solution 2

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.

Solution 3

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

Share:
35,654
Victor
Author by

Victor

Java developer, working on enterprise systems

Updated on March 27, 2021

Comments

  • Victor
    Victor about 3 years

    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?

  • Eng.Fouad
    Eng.Fouad over 10 years
    But wouldn't that consume a lot of memory? Especially for large programs that use a lot of strings?
  • SLaks
    SLaks over 10 years
    @Eng.Fouad: No, unless they're interned.
  • Hot Licks
    Hot Licks over 10 years
    Keep in mind that "literal strings" occupy storage because they're effectively a part of your program. They have to be there or your program will be missing something.
  • Stephen C
    Stephen C over 10 years
    "strings in the intern pool will never be GC'd." - That's not correct for a modern Hotspot JVM. It is more complicated ...
  • JaskeyLam
    JaskeyLam over 9 years
    "will HelloWorld" still be interned when we use "new String("HelloWolrd");"?
  • Stephen C
    Stephen C over 9 years
    @Jaskey - the String that you just created with new will not be interned. The String object that represents the string literal will be interned.
  • Raman Sahasi
    Raman Sahasi over 5 years
    Please note: This answer is obsolete and doesn't apply to modern JVMs.
  • Stephen C
    Stephen C almost 5 years
    @RamanSahasi - It is not obsolete. It was never completely correct in the first place.
  • Stephen C
    Stephen C over 3 years
    "String objects which are in the string pool will not be garbage collected." - This is incorrect. The string pool >>is<< garbage collected, and has been since (I think) JDK 1.1. (In JDK 1.6 and earlier, if you used CMS you needed to set a JVM option to enable PermGen GC. But CMS was never the default GC.)
  • Stephen C
    Stephen C about 3 years
    There are a number of misstatements in this answer. The reason that string literals were (and are) unlikely to be garbage collected is that the classes that declared them normally remain reachable for the application's entire lifetime. This is true whether or not the string pool is in permgen or the regular heap. (The permgen >was< garbage collected.)