Core Javacritical

String Pool & Interning

String literals in Java are stored in a shared pool (String constant pool) in the heap. Two literals with the same content share the same object. String.intern() can add a heap-allocated String to the pool and return the canonical reference.

Memory anchor

String Pool = a hotel lost-and-found box. Identical umbrellas share one slot. But 'new String()' is buying a brand-new umbrella even though an identical one is already in the box.

Expected depth

The string pool is stored in the heap (moved from PermGen in Java 7). String literals are automatically interned at class load time. new String("hello") always creates a new heap object even if the pool contains "hello". Interning is useful for memory deduplication when storing large numbers of repeated strings, but excessive interning fills the pool and increases GC root scanning time. String is immutable — its hash is lazily cached on first hashCode() call.

Deep — senior internals

The string pool is implemented as a hash table in native code (StringTable). Its default capacity is 65536 buckets in Java 11+ (configurable via -XX:StringTableSize). Java 9 introduced compact strings — strings are stored as byte[] (Latin-1 if all chars fit, UTF-16 otherwise) rather than char[], halving memory for ASCII-heavy workloads. String.intern() is a native method with non-trivial cost — benchmarks show it can be a bottleneck under high concurrency due to StringTable locking. G1 GC introduced string deduplication (-XX:+UseStringDeduplication) which deduplicates char arrays in the background without interning.

🎤Interview-ready answer

String literals are automatically interned into the JVM's string pool (heap-resident since Java 7). Two literals with the same content are == equal because they reference the same pooled object, but new String("x") allocates a new heap object that is != the pooled one. Always use .equals() for string value comparison. String.intern() manually adds a string to the pool and returns the canonical reference — useful for deduplication, but has throughput cost under contention.

Common trap

"abc" == "abc" is true (both are pooled literals), but new String("abc") == "abc" is false — this trips up developers who compare strings with == and only test with literal values in unit tests.

Related concepts