Does the garbage collector count this as a collectable object?

Given a string

String x = "hello";

As far as I remember, x now is a constant with a reference but when in the middle of the code I change value to

x = "hey";

hello stays stuck in the memory and the GC frees it. Is it true ? If not, could you explain more how the GC work?


Solution 1:

As far as I remember, x now is a constant

No. The reference is not a constant. It is a reference to an immutable, but the reference itself (the "pointer") is not (crediting Turing85 for the clarification). For x to be considered a constant, it needs to be declared with the keyword final (then the reference itself will be a constant). For example, final String x = "hello";. Because it is not a constant, it allows you to change the reference later on in the code x = "hey";. THAT SAID, because of how Java manages strings (and other immutables), "hello" and "hey" are indeed constants. They are "permanent" members of the String pool. Meaning that, their life cycle is the same as the life of your program. I think there are ways change this, but by default I am pretty sure this is the case. So, if you create multiple objects with the same String value:

String a = "hello"; // will add "hello" to String pool if it doesn't exist there
String b = "hello"; // finds "hello" in the string pool and returns back the same reference to this variable
String c = "hello"; // same as `b` above

However, if you create a new String using the copy constructor:

String d = new String("hello"); // Will add new "hello" to heap even though it already exist in string pool. (Thanks Holger!)

Explaining in detail how the GC works is not very easy to explain; especially in a single SO post. I don't even fully understand it myself. But, since the purpose of the pool is to eliminate the need to create "infinite" copies of the same thing over and over, "hello" and "hey" won't be garbage-collected. As for the variable x, it will be handled by the GC depending on many factors, one of which is scope. Also, there is no guarantee as to when (if ever) the GC will cleanup an unused resource.

I think this is accurate, albeit somewhat ambiguous or incomplete. But at a high-level, this is how GC will work in this case to the best of my knowledge.

UPDATE: Thanks to @Holger for bringing this to my attention. When a String Literal is assigned to a variable, it will first look for such value in the String Pool to see if such string exists. If it doesn't, it creates it and assigns it to the variable. HOWEVER, when a string is created with the new operator, it will add the new string JUST into Heap Memory. That's the main difference between assigning string literals vs. new strings to a variable.