String.intern() and the String Pool — How They Work and When to Use intern()
Fast recall
Quick revision
Core answer
String instances. Every string literal ("hello") is automatically interned — placed in the pool and reused. `s.intern()` returns the pool's copy of s if one exists; otherwise it adds s to the pool and returns it. Use intern() only when you know you'll have many duplicates of the same value (e.g., loading a large CSV with millions of rows sharing a few hundred category strings) — sharing saves memory. Don't blanket-intern: the pool has a hash-table cost, intern() itself is slow, and interned strings live in the heap (Java 7+) so they're GC-eligible but add hash-table overhead. Java 9+ compact strings plus new String("...").intern() patterns are mostly obsolete — use String.intern() surgically, not as a default habit.Whether the candidate understands the pool semantics, knows that literals are auto-interned, and can articulate when intern() helps vs hurts
Thinking every `String` is automatically interned (only literals are). Using `==` to compare strings, relying on interning. Calling `intern()` on every string as 'an optimization'
Mention that Java 7 moved the string pool from PermGen to the heap (preventing PermGen OOM from excessive interning). Discuss `-XX:StringTableSize` for tuning the pool hash table. Know when `Map<String, String>` deduplication is a better choice than `intern()`
Interview-ready guide
Interview answer
The string pool is the JVM's deduplication cache — one String instance per unique character sequence.
What gets pooled automatically
- String literals:
"hello"is interned on class load - Compile-time constant expressions:
"a" + "b"becomes the literal"ab"and is pooled
What does NOT get pooled
new String("hello")— thenewforces a distinct object- Strings built at runtime: concatenations with variables,
split()results, JSON parsing
`intern()` semantics
s.intern()returns the pool's copy ofsif one exists, otherwise addssto the pool and returns it- After interning,
==works for equal strings — but relying on this is fragile
When `intern()` helps
- Loading big data with heavy duplication — CSV rows, log parsing, repeated JSON keys
- Long-lived strings where the cost amortizes
When `intern()` hurts
- Short-lived strings — you pay a hash-table insert/lookup cost for no benefit
- High-cardinality data — every value is unique; interning just bloats the pool
- As a universal habit — real profiling shows microsecond cost per call, which adds up
Modern alternatives
- Local
Mapdeduplication inside a batch or request — bounded, scope-controlled, doesn't touch the JVM-wide pool - Java 9+ compact strings (
byte[]+ coder flag for Latin-1) already reduce per-string memory, weakening the case for aggressive interning
Historical note
- Java 7 moved the pool from PermGen to the regular heap; interned strings are now GC-eligible when unreferenced
-XX:StringTableSizetunes the pool hash table size — default around 65K buckets is fine for most apps
Recommendation: Use String.intern() surgically — only when a heap dump shows string duplication is a real problem and the values are long-lived. For request-scoped deduplication, a local HashMap is usually cleaner. And always use .equals() for comparison — the == optimization after interning is fragile and .equals() has a reference-identity fast path anyway.
`String.intern()` and the String Pool — How They Work and When to Use `intern()`
Direct Answer
The string pool is a JVM-managed set of unique String instances. Every string literal ("hello") is automatically interned — placed in the pool and reused. s.intern() returns the pool's copy of s if one exists; otherwise it adds s to the pool and returns it. Use intern() only when you know you'll have many duplicates of the same value (e.g., loading a large CSV with millions of rows sharing a few hundred category strings) — sharing saves memory. Don't blanket-intern: the pool has a hash-table cost, intern() itself is slow, and interned strings live in the heap (Java 7+) so they're GC-eligible but add hash-table overhead. Java 9+ compact strings plus new String("...").intern() patterns are mostly obsolete — use String.intern() surgically, not as a default habit.
Common Mistakes & Pitfalls
Thinking every String is automatically interned (only literals are). Using == to compare strings, relying on interning. Calling intern() on every string as 'an optimization'
Check your understanding
Answer these without looking back at the article.
- Why did Java 7 move the string pool from PermGen to the regular heap?
- How does the JVM decide which strings to intern automatically at class load time?
- What does `-XX:StringTableSize` tune, and when would you change it?
- What's the trade-off between `String.intern()` and a local `Map<String, String>` for deduplication?
- Why is relying on `==` for string comparison after `intern()` considered fragile?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.