Hello everybody, I am trying to learn about the way the String Pool works in Java in a high level of detail, but I cannot, for the life of me, find official docs explaining it.
I was under the impression that the String Pool would never get GCed, but this is in fact not the case after Java 6, as far as my research tells me.
The String Pool is now a member of the Heap and is eligible for GC, but it seems that some special rules apply to string literals, namely, that every
method that uses a string literal, holds an implicit reference to it, so for the whole duration of the method, the string object in the pool is not eligible for GC,
since it is not unreferenced (source: the accepted answer of this StackOverflow Thread)
This would mean, that in such a situation:
When the s1 reference goes out of scope (the inner scope), even if a minor GC event is triggered, the string object of the pool would not be collected. Not until method "Foo" finishes executing.
Is there any way to confirm this officially? Anything referenced in a specification?
Petros Papatheodoru wrote:When the s1 reference goes out of scope (the inner scope), even if a minor GC event is triggered, the string object of the pool would not be collected. Not until method "Foo" finishes executing.
This is not correct. As the Stack Overflow thread which you linked to says, that string object cannot be garbage-collected until it is certain that method Foo will never again be executed. So as long as the class which contains that method is still loaded, it's possible that Foo could be executed at some future time.
The SO thread goes on to talk about situations in which a class might be unloaded and thus possibly allow for garbage collection of string literals created by that class. But it doesn't go into details about how a garbage collector might identify such string literals and it doesn't say that any garbage collectors actually do that. I would also remind you that there is more than one garbage collector, which makes the task of finding out how "the garbage collector" works more difficult. (There's even a garbage collector whose only feature is that it never collects any objects.)
Petros Papatheodoru wrote:it seems that some special rules apply to string literals, namely, that every method that uses a string literal, holds an implicit reference to it, so for the whole duration of the method, the string object in the pool is not eligible for GC
Not quite. Methods aren't objects and so they can't contain references to any objects. Instead, it's the class which naturally holds references to its objects. This includes the String literals which it contains. If I'm not mistaken its String literals are all added to the String pool at the time the class is loaded. If you're interested in a high level of detail about the String pool, you might want to look into that.
But even if the String literals were loaded into the String pool lazily (i.e. only the first time a method containing one would cause it to be added to the pool), it still wouldn't make sense for a String to be available for GC after calling a method caused it to be loaded. If, for example, that was a method which was run hundreds of thousands of times, that could result in its being repeatedly added to the pool and then garbage-collected. That would be a waste of time. So my expectation is that a String in the pool isn't available for GC until the class which caused it to be put there has been unloaded. Or more precisely, until all of the classes which caused it to be put there have been unloaded.
One of my first interactions with Team CodeRanch where I was exposed to be "That Guy" was showing how in recent versions of Java, it appeared that the String Constants now DO get interned lazily, rather than at load time as in days of yore.
There was widespread consensus that this was way beyond the scope of either the OCPJP or whatever one should know to be a good Java programmer, but I had found either an explanation of a sample code example or a mock exam question that was just "wrong" in this way and wouldn't let it go until everyone agreed a. that it behaved differently than most extant descriptions implied or stated and b. almost nobody cared, it was the JVM's business and not something those trying to write Java code should think or care about. Some authoritative persons chimed in and said "Definitely out of scope for the exam, let it go!"
I think it was the first time I really bothered to read more than a few lines of the JLS, so that was good, at least.
RTFJD (the JavaDocs are your friends!) If you haven't read them in a long time, then RRTFJD (they might have changed!)
Jesse Silverman wrote:One of my first interactions with Team CodeRanch where I was exposed to be "That Guy" was showing how in recent versions of Java, it appeared that the String Constants now DO get interned lazily, rather than at load time as in days of yore.
Oh yeah, that thread. I was definitely in the "don't care" group so I didn't post to the thread. However other people's mileage may vary, and if they want to learn more about the minutiae of garbage collection in Java then I'm certainly not going to bug them about it. Go for it, I say.