Symbol objects are subject to garbage collection, but the "namespace"
and "name" strings that identify them are not. Those strings are
"interned" via the "intern" method on java.lang.String. Once a String
is interned, there exists a single canonical String object that
represents it throughout the remaining lifetime the JVM instance. Any
two Symbols of the same namespace and name will reference those
canonical namespace and name strings and will thus have identical
namespaces and names.
Not interning the Symbols themselves turns out to be important in
Clojure because it allows two Symbols with identical namespace and
name to have different metadata.
Keyword objects are interned by Clojure and are not garbage collected.
When a Keyword is created, it's placed in a ConcurrentHashMap that
maps a Symbol of the same name and namespace to the Keyword object. In
a given JVM instance, there is at most one Keyword object with a given
name and namespace. Whenever the reader reads a Keyword's text
representation, it returns the unique Keyword object associated with it.
Here's some repl playing to support this:
user=> (identical? 'a/b 'a/b)
false
user=> (identical? (name 'a/b) (name 'a/b))
true
user=> (identical? (namespace 'a/b) (namespace 'a/b))
true
user=> (= (quote #^{:tagged true} a/b) (quote a/b))
true
user=> (= (meta (quote #^{:tagged true} a/b)) (meta (quote a/b)))
false
user=> (identical? :a/b :a/b)
true
--Steve
Right you are. On reading further, I see that unreferenced interned
Strings can be collected in Java 1.2+ because the interning mechanism
holds only a weak reference to them.
Thanks for the correction.
--Steve