When Will a String Be Garbage Collected in Java

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:

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

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.

Sample Image

Read more...

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

how does garbage collection with respect to Strings in Java?

I can see one scenario where trimming down an array causes memory leak
and hence setting its reference to null is a good way to garbage
collect those obsolete references.

Strings are reference types, so all the rules for reference types with respect to garbage collection apply to strings. The JVM may also do some optimizations on String literals but if you're worrying about these, then you're probably thinking too hard.

When does the JVM collect unreferenced objects?

The only answer that matters is: you can't tell and it needn't ever, but if it does you can't know when that will be. You should never write Java code around deterministic garbage collection. It is unnecessary and fraught with ugliness.

Speaking generally, if you confine your reference variables (including arrays or collections of reference types) to the narrowest possible scope, then you'll already have gone a long way toward not having to worry about memory leaks. Long-lived reference types will require some care and feeding.

"Trimming" arrays (unreferencing array elements by assigning null to them) is ONLY necessary in the special case where the array represents your own system for managing memory, eg. if you are making your own cache or queue of objects.

Because the JVM can't know that your array is "managing memory" it can't collect unused objects in it that are still referenced but are expired. In cases where an array represents your own system for managing memory, then you should assign null to array elements whose objects have expired (eg. popped off a queue; J. Bloch, Essential Java, 2nd Ed.).

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)

Are objects in string constant pool eligible for garbage collection?

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.

What happens to Strings inside String[] after String[] is garbage collected?

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 Topics



Leave a reply



Submit