3

As I know, intern method is supposed to return the String from the String pool if the String is found in String pool, otherwise a new string object will be added in String pool and the reference of this String is returned.

String s = "a";
s = "b";
String str = new String("a").intern();

What will happen in this scenario... Is there two case exists

  1. Till "a" is not garbage collected, and String str = new String("a").intern(); executes str will refer this "a"
  2. If "a" is Gc'ed then a new object will be created and str will refer a new "a";

Or "a" is never eligible for garbage collection?

Simeon Visser
  • 118,920
  • 18
  • 185
  • 180
Rajesh
  • 213
  • 4
  • 15

4 Answers4

3

This is different in different JVMs. For example,

OpenJDK/Hotspot Java 6: The string literals are in the PermGen and AFAIK, only cleaned up on a Full GC (not just a major collection of the tenured space)

OpenJDK/Hotspot Java 7: The strings literals are in the Heap and can be collected at anytime they are not referenced, however I suspect they are held by the PermGen which used in code.

OpenJDK/Hotspot Java 8: There is no PermGen so Strings should be cleaned up more freely even if held by Classes which will now be in the heap.

1) There is only one String literal and it will not be GC'ed until there is no references to it, possibly in cde as well which can be when the ClassLoader unloads, if it does ever.

2) It is possible that the first "a" and second "a" and third one you create are all different Strings if they get GC'ed in between.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • If we ignore the scenario when ClassLoader unloads, Then what i explained as two case is true.... Did i get it clear? – Rajesh Dec 24 '13 at 14:22
  • @Rajesh The exact lifecycle is not defined. It might never be GC'ed but it could be esp in future versions. Note: if you create new intern()ed Strings they are cleaned up. – Peter Lawrey Dec 24 '13 at 15:41
2

The Java specification does not formally prohibit garbage collection of String constants when their containing classes go out of scope, but any two String literals with identical contents must refer to the same String object, and the return value of String#intern() must be the same object that would be referred to by a literal with the same contents.

Whether a given JVM actually garbage-collects String objects from the run-time constant pool is an implementation detail, but the reachability rules for String instances given those requirements would be that a String in the constant pool is reachable if any reachable variable holds a reference to it or if any class with that literal is loaded.

In your specific scenario, the String literal "a" is eligible for garbage collection when:

  • all references to it are eliminated (including the first value of s and str, which refer to the same object, which is in the constant pool) and
  • all classes which have a String constant with the contents "a" are unloaded.
chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • If code persists the identity hash value of a string literal but doesn't hold any actual reference to it, and if the code using the literal is called again, would it be legal for the identity hash value to change? – supercat Dec 26 '13 at 03:27
2
  1. "a" is placed in the constant pool by the compiler and class loader.
  2. It cannot be garbage-collected until no references to it exist.
  3. 's' is a reference to "a" in your first line of code.
  4. Your second line of code yields another reference to it.
  5. Therefore "a" cannot be garbage-collected while either 's' or 'str' is reachable.
  6. Therefore your final question numbered (2) doesn't begin to make sense, as the preconditions for it cannot possibly occur,
user207421
  • 305,947
  • 44
  • 307
  • 483
  • My doubt is second line of code made "b" to refer for s, so at this particular time "a" is not referenced by anything... Is there a possibility exists that "a" is GC'ed, If yes then definitely Third line of code will create a "a" in string pool, but if no...then the same "a" will be referenced by str? – Rajesh Dec 24 '13 at 21:26
0

As others have mentioned, the behaviour is an implementation detail. One way to find out is to only reference the String using a WeakReference then force a garbage collection and see if the WeakReference has been cleared.

Here's some example code:

// Only keep a weak reference to a
String str = "a";
WeakReference<String> strRef = new WeakReference<String>(str);
str = null;

// Attempt to force GC
Object obj = new Object();
WeakReference<Object> ref = new WeakReference<Object>(obj);
obj = null;
while(ref.get() != null) {
  System.gc();
}

// Wait a bit a second to make sure GC has actually run
Thread.sleep(1000);
// Print the result
if (strRef.get() == null) {
  System.out.println("String \"a\" has been garbage collected");
} else {
  System.out.println("String \"a\" has not been garbage collected");
}

On my machine using JavaSE-1.7 the String is not garbage collected.

Community
  • 1
  • 1
JamesC
  • 1