0

So a new String("abc"); creates an object in Heap & a literal "abc" in the String pool as per many of the answers I found. Since the new keyword was used, there should be no references to the String literal in the pool.

Does this mean -

a. The literal will be GC'ed in the next run (assuming no other references were created to the literal later on)?

b. If (the answer to a is) yes, it sounds fairly easy for JVM to free the literal in the pool as soon as the object is created, instead of waiting for GC. Why is this not done?

c. If (the answer to a is) no, what would be the reason for the an unreachable literal to not be GC'ed?

dj_rai
  • 71
  • 6
  • a. Yes b. Removing objects is the job of the GC. I don’t know, but in my ears it sounds like it would complicate things too much if other parts of the JVM began removing stale objects too. Also there would be very minimal gain if any. – Ole V.V. Aug 16 '20 at 04:33
  • 1
    @OleV.V. - Actually "a. No". See my answer. – Stephen C Aug 16 '20 at 05:27
  • I believe you, @StephenC. I did not understand the explanation in your answer, but never mind about that. – Ole V.V. Aug 16 '20 at 11:58

2 Answers2

2

Since the new keyword was used, there should be no references to the String literal in the pool.

That is not correct. There is probably1 a reachable reference to the String object that corresponds to the literal. My recollection is that the reference is stored in the same "frame" that holds the static fields for the class. In practice, this reference will continue to be reachable until the enclosing class is unloaded by the garbage collector. (That typically never happens.)

So the answers are:

a. The literal will be GC'ed in the next run (assuming no other references were created to the literal later on)?

No.

c. If (the answer to a is) no, what would be the reason for the an unreachable literal to not be GC'ed?

The String object corresponding to the literal is NOT unreachable. For example, it needs to be reachable if there is any possibility that the new String("abc") statement could be executed again.

Since it is difficult for the JVM runtime to determine that a statement (that was determined to be reachable at compile time) won't be executed more than once at runtime, and since there is little performance benefit in doing that, the runtime assumes that all string literals need to be reachable for the lifetime of the Java classes2 that define them.

Finally, as @Holger points out, it makes no practical difference when String literal objects become unreachable. We know that they will be present (in some form) if they are needed. That's all that really matters.


1 - The actual behavior is highly implementation dependent. In early JVMs, the String objects for class literals were interned eagerly. Later on this changed to lazy interning. It would even be possible to re-intern a String object every time the string literal is used, though this would be very inefficient in general. Then we need to consider various things that optimizer could do. For example, it could notice that the String object for the literal never escapes and is used in a way that doesn't actually require interning. Or it could notice that the entire expression could be optimized away.

2 - I mean classes. The things that correspond to a Class object. Not instances of those classes.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 1
    Thanks Stephen. Based on [link](https://www.oracle.com/java/technologies/tuning-garbage-collection-v50-java-virtual-machine.html), **An object is considered garbage when it can no longer be reached from any pointer in the running program**. In the above case of `new String("abc")`, how does Java maintain a pointer to the literal created? – dj_rai Aug 16 '20 at 05:37
  • It is in an internal data structure ... that you can't see unless you start digging into the native code generated by the JIT compiler. But it is certainly there, because the `String` object for the literal is only created once. (I think the reference is stored in the same frame that holds a classes static variables.) – Stephen C Aug 16 '20 at 05:39
1

Since new String("abc"); is object and not interned it will be garbage collected in next GC run.

  • However GC won't be immediately running just to collect this string object due to various performance reasons & availability of space.

  • Using System.gc(); also doesn't guarantee that it'll run (this is just suggestion to the GC to run.)

GC runs with many reason few are like below (also depends on VM)

More Memory allocation in specific generation is failling. Heap allocation Or Objects presence reaching threshold etc.

Rahul Sawant
  • 1,223
  • 9
  • 12
  • Keep in mind that there are two `String` objects involved in `new String("abc")`, the string literal `"abc"`, which is interned, and the `String` created via `new`, which is not interned. Both have the same contents. – Slaw Aug 16 '20 at 05:27
  • The question is actually about whether the literal will be garbage collected. (Not the object created by the `new` operator.) – Stephen C Aug 16 '20 at 05:31