21

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:

  1. If a string is defined as literal at compile time [e.g: String str = "java"] then will it be garbage collected?

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

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

Aleš
  • 8,896
  • 8
  • 62
  • 107
Lokesh
  • 7,810
  • 6
  • 48
  • 78
  • 3
    1 - http://stackoverflow.com/questions/2202162/garbage-collection-and-strings ; 2 - http://stackoverflow.com/questions/6470651/creating-a-memory-leak-with-java ; 3 - String a = new String("asd") -> "a" reference will be garbage collected, but is just a reference to "asd" and "asd" will be there forever. – user1050755 Mar 10 '13 at 15:54
  • 1
    If you search more you will find places mentioning that String literals created using intern can be garbage collected as they use weak reference but i can't confirm it and thats the reason why i have posted as there are lots of mixed responses. – Lokesh Mar 10 '13 at 15:57
  • 2
    “From Java 7 onwards, the Java String Pool is stored in the Heap space, which is garbage collected by the JVM. The advantage of this approach is the reduced risk of OutOfMemory error because unreferenced Strings will be removed from the pool, thereby releasing memory.” [*Guide to Java String Pool* by baeldung](https://www.baeldung.com/java-string-pool) – Ole V.V. Dec 21 '18 at 04:03
  • Ole V.V. has the correct answer – csguy May 08 '19 at 00:07

4 Answers4

19

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

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    For #1, When you say code objects that contain references to String literals, what are you referring to? – Mercenary Nov 12 '13 at 14:00
  • 4
    Somewhere in the code objects (bytecode or native compiled) there will be instructions that need to fetch the reference to the String object that correspond to the literal. Either the reference is embedded in the code itself, or it is stored in a private frame that is associated with the code. Either way, the reference is "reachable" so long as the code *could* be executed. – Stephen C Nov 13 '13 at 05:10
  • Thanks. And, is string intern pool part of the method area in JVM? – Mercenary Nov 13 '13 at 10:30
  • No. It is a separate data structure. But if you are really interested, I suggest you download the OpenJDK source code and examine it for yourself. – Stephen C Nov 13 '13 at 10:37
10

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

jacobm
  • 13,790
  • 1
  • 25
  • 27
  • 2
    This is incorrect. The PermGen space >>is<< garbage collected. – Stephen C Mar 10 '13 at 16:07
  • You are right of course. My intent was just to say that data allocated into permgen won't get GC'ed under normal circumstances, but I misphrased. Slightly rephrased. – jacobm Mar 10 '13 at 16:12
  • Actually, digging deeper, I discovered that it's no longer true that interned strings don't get garbage collected. (This isn't because of permgen space, it's due to the implementation of `String#intern`.) Changing my answer to reflect that. – jacobm Mar 10 '13 at 16:38
  • 1
    It was *never* true that interned strings don't get garbage collected. – Holger Jan 25 '16 at 15:36
0
  1. The literal string will remain in memory as long as the program is in memory.
  2. str will be garbage collected, but the literal it is created from will not.
  3. That makes perfect sense, since the string class is unloaded when the program is unloaded.
fredrik
  • 6,483
  • 3
  • 35
  • 45
  • Can you give me an example where String can be unloaded? As i believe String literals must be used within java classes also and as String literals are constants, unloading might need unloading of CLassLoader as per my knowledge. Do you agree? – Lokesh Mar 10 '13 at 16:04
  • A string literal cannot, to my knowledge be unloaded programatically. They will be unloaded, or destroyed, when the program terminates. – fredrik Mar 10 '13 at 16:06
  • 2
    @fredrik - they can also be garbage collected if a class that has been dynamically loaded is unloaded. And that can happen while the JVM is running normally. – Stephen C Mar 10 '13 at 17:27
-3

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.

AmitG
  • 10,365
  • 5
  • 31
  • 52