How does String pool work and how is it related to immutability?
If strings could be changed, modifying one string would affect all others that reference it:
Junior Level
String Pool is a special memory store where Java keeps only one copy of each unique string.
String a = "Hello";
String b = "Hello";
System.out.println(a == b); // true — the same string from the pool
Why this only works with immutable strings
If strings could be changed, modifying one string would affect all others that reference it:
// Hypothetically — if strings were mutable
String a = "Hello";
String b = "Hello"; // same reference from the pool
a.changeTo("World"); // breaks b too!
The intern() method
String s1 = new String("Hello"); // new object in heap
String s2 = s1.intern(); // adds to pool, returns reference
String s3 = "Hello"; // from the pool
System.out.println(s2 == s3); // true
Middle Level
How it works
- At compile time — all string literals go into the class constant table
- At load time — JVM checks the pool: if the string exists — returns reference, if not — creates a new one
- At runtime —
intern()adds a string from heap to the pool
Memory evolution
- Java 6: String Pool was in PermGen (limited size, frequent OOM)
- Java 7u6+: String Pool moved from PermGen to regular Heap (managed by GC)
Advantages
- Memory savings — duplicate strings are not created
- Fast comparison — interned strings can be compared via
==in O(1) (one CPU instruction — reference comparison), whereasequals()iterates over all characters. - Cached hashCode — computed once
When to use intern()
- Many repeated strings (keys, configuration constants)
- Keys in
HashMapwith billions of entries (savings on duplicates)
Senior Level
Connection to immutability
Immutability is a prerequisite for String Pool. The Flyweight pattern at the language level only works because Java guarantees: String contents will never change.
Performance
- Comparison via
==for interned strings — O(1), but in business logic still useequals() - Cached
hashCodespeeds upHashMap— repeated lookups don’t require recomputation
Risks of intern()
- Memory leak — strings from the pool are not GC’d as long as the ClassLoader is alive
- PermGen/Heap OOM — too many unique strings via
intern()can overflow memory - In Java 7+ the pool is in Heap, but strings can still live a very long time
Summary for Senior
- String Pool — Flyweight pattern at the language level
- Works only thanks to the immutability guarantee
- Pool in Heap (Java 7+), managed by GC
intern()— powerful but dangerous: monitor the volume of unique strings
Interview Cheat Sheet
Must know:
- String Pool — store of unique strings, works ONLY thanks to immutability (Flyweight)
- Literals go into the pool at class load,
intern()adds a string from heap - Java 6: pool in PermGen (frequent OOM); Java 7+: pool in Heap (managed by GC)
- Comparison of interned strings via
==— O(1), but in business logic useequals() - String caches hashCode — computed once, speeds up HashMap
- Risks of intern(): memory leak, Heap OOM with too many unique strings
Frequent follow-up questions:
- Why is the pool impossible without immutability? — Changing one string breaks all references to it
- When to use intern()? — Many repeated strings, keys in huge HashMaps
- Is intern() safe? — Pool strings are not GC’d as long as ClassLoader is alive — risk of OOM
- Do Compact Strings affect the pool? — No, the pool works independently; Compact Strings save 50% memory
Red flags (do NOT say):
- “String Pool is in PermGen” — since Java 7+ it’s in Heap
- “intern() always speeds things up” — with abuse it causes OOM
- “Comparing strings via == is fine after intern()” — in business logic always use equals()
- “The pool copies strings” — literals are placed in the pool at class load
Related topics:
- [[4. Why is String class immutable]]
- [[5. What are the consequences of String immutability]]
- [[19. Can you change String value via reflection]]
- [[27. Can you use immutable objects as keys in HashMap]]