String Pool
String interning and memory optimization
Interview Relevant: Common interview question
6 min read
The String Pool (String Intern Pool)
The String Pool is a special memory region in the heap where Java stores string literals. It enables memory optimization by reusing immutable String objects.
How String Pool Works
- String literals are automatically stored in the pool
- Duplicate literals share the same reference
new String()creates objects outside the poolintern()method adds strings to the pool
🔑 Memory Layout:
Heap Memory
├── String Pool
│ ├── "Hello" ← s1, s2 both point here
│ └── "World"
└── Regular Heap
├── String("Hello") ← s3 points here
└── String("Hello") ← s4 points here
⚠️ Java 7+ Change: String Pool was moved from PermGen to Heap, making it eligible for garbage collection.
Code Examples
String Pool vs new String()
java
1// String Pool demonstration
2String s1 = "Hello"; // Created in String Pool
3String s2 = "Hello"; // Reuses same object from Pool
4String s3 = new String("Hello"); // New object in heap (NOT pool)
5String s4 = new String("Hello"); // Another new object in heap
6
7// Reference comparison
8System.out.println(s1 == s2); // true (same pool reference)
9System.out.println(s1 == s3); // false (pool vs heap)
10System.out.println(s3 == s4); // false (different heap objects)
11
12// Content comparison (always true for same content)
13System.out.println(s1.equals(s2)); // true
14System.out.println(s1.equals(s3)); // true
15System.out.println(s3.equals(s4)); // trueUsing intern() to add strings to pool
java
1// intern() method - Add string to pool
2String s1 = new String("Hello"); // Heap object
3String s2 = s1.intern(); // Returns pool reference
4String s3 = "Hello"; // Pool reference
5
6System.out.println(s1 == s2); // false (heap vs pool)
7System.out.println(s2 == s3); // true (both from pool!)
8
9// Practical use of intern()
10String dynamicString = new String("Dynamic").intern();
11String literal = "Dynamic";
12System.out.println(dynamicString == literal); // true!
13
14// Runtime string interning
15Scanner scanner = new Scanner(System.in);
16String input = scanner.nextLine().intern(); // Add user input to pool
17
18// Use intern() when:
19// 1. You have many duplicate strings
20// 2. You want == comparison for performance
21// 3. Memory optimization is criticalCompile-time vs runtime string creation
java
1// Compile-time vs Runtime strings
2String s1 = "Hello"; // Compile-time literal → Pool
3String s2 = "Hel" + "lo"; // Compile-time constant → Pool!
4String s3 = "Hel";
5String s4 = s3 + "lo"; // Runtime concatenation → Heap!
6String s5 = s4.intern(); // Explicitly add to Pool
7
8System.out.println(s1 == s2); // true (both from pool)
9System.out.println(s1 == s4); // false (s4 is on heap)
10System.out.println(s1 == s5); // true (s5 interned to pool)
11
12// final variables are compile-time constants
13final String hello = "Hello";
14final String world = "World";
15String message = hello + world; // Optimized at compile time!
16
17String literal = "HelloWorld";
18System.out.println(message == literal); // true!
19
20// Non-final variables prevent optimization
21String h = "Hello";
22String w = "World";
23String msg = h + w; // Runtime concatenation
24System.out.println(msg == literal); // false!Memory optimization strategies
java
1// Memory optimization with String Pool
2// Scenario: Processing 1 million records with repeated values
3
4// WITHOUT interning (wasteful)
5List<String> countries = new ArrayList<>();
6for (int i = 0; i < 1_000_000; i++) {
7 // Creates new String each time!
8 countries.add(new String("USA"));
9}
10// Memory: ~1 million String objects!
11
12// WITH interning (optimized)
13List<String> countriesOptimized = new ArrayList<>();
14for (int i = 0; i < 1_000_000; i++) {
15 // All share same pool reference
16 countriesOptimized.add("USA");
17}
18// Memory: 1 String object + references
19
20// Manual interning for dynamic data
21List<String> fromDatabase = new ArrayList<>();
22for (String country : fetchCountriesFromDB()) {
23 fromDatabase.add(country.intern()); // Intern dynamic data
24}
25
26// Caution: Don't over-use intern()
27// - Interning has overhead
28// - Pool lookup takes time
29// - Only beneficial for repeated stringsUse Cases
- Memory optimization with repeated strings
- Fast equality checks with ==
- Processing large datasets with duplicates
- Configuration value caching
- Symbol tables in compilers
- Reducing GC pressure
Common Mistakes to Avoid
- Relying on == for string comparison
- Over-using intern() (has overhead)
- Not understanding compile-time optimization
- Assuming all strings are in the pool
- Memory leaks from excessive interning (pre-Java 7)
- Confusing String Pool with string caching