You almost never really lose all references to string literals and constant expressions (note I'm not including strings returned by the intern() method here). Whatever code fragment they're used in, the JVM never knows when you're going to call that method or constructor again, and you'd need that String object again. So it keeps them all. The only times the system could be sure a given String literal / constant is no longer needed are: (a) if the string constant is only used in a staic initializer or static variable initialization expression, which is only run once when the class is loaded, or (b) if all references to all instances of the class have been lost, and the class itself is garbage collected (not just the individual instances). These cases are sufficiently rare that it's not worth the JVM's time to try to do a little extra GC, in my opinion.
As for strings returned by the intern() method - it
is possible to lose all references to those strings, other than the one that's kept in the string pool. There isn't really any good reason I can think of for the string pool to continue keeping that last reference, other than the fact that the
Java Language Specification makes no provision for ever removing anything from the intern pool. It can be argued that the JLS doesn't expressly forbid it either, but I think this is ignoring the clear intent of the wording used by the JLS. In any event, I know of no JVM implementation that does ever remove anything from the intern pool - if there is one, I'd like to hear about it.
So, the end result is that anything put in the String intern pool will be there as long as the JVM continues running. This isn't normally a problem - string literals would have to be stored in memory somewhere anyway. But it is something to keep in mind if you're calling the intern() method very often yourself - you can fill up memory this way, and it's impossible to free afterwards.