The specification does not mandate a behavior. All it requires, is that all string literals (and string-typed compile-time constants in general) expressing the same string, evaluate to the same object at runtime.
At run time, a string literal is a reference to an instance of class String
(§4.3.3) that denotes the string represented by the string literal.
Moreover, a string literal always refers to the same instance of class String
. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.29) - are "interned" so as to share unique instances, as if by execution of the method String.intern
(§12.5).
Its also repeated in JLS §15.29:
Constant expressions of type String
are always "interned" so as to share unique instances, using the method String.intern
This implies that each Java implementation maintains a pool at runtime which can be used to look up the canonical instance of the string. But the pool doesn’t have to hinder garbage collection. If no other reference to the object exists, the string instance could be garbage collected, as the fact that a new string instance has to be constructed when necessary, is unobservable.
Note that when you add strings to the pool manually, by invoking intern()
, the string instances may indeed get garbage collected when otherwise being unreachable.
But in practice, the common implementations, like the HotSpot JVM associate a reference from the code location to the string instance after the first execution, so the object is referenced by the code containing the string literal or compile-time constant. So, the object associated with the string literal can only get garbage collected, when the class itself gets garbage collected. This is only possible when its defining class loader and in turn, all other classes defined by this loader are unreachable too.
For the application class loader, this is impossible. Class unloading can only happen for additional class loader created at runtime. Then, the string instances created for compile-time constants within classes loaded by this class loader may get garbage collected, if not matching constants in other code.