The String Constant Pool

The String Constant Pool is a JVM-wide cache of string literals: when different parts of your code reference a string with the same content, they can share a single String object instead of allocating a new one each time. This is possible only because String is immutable in Java, combined with the String interning mechanism. In other words, the pool is an application of the Flyweight design pattern.

String Pool Examples

String s1 = "Hello";
String s2 = "Hello";
String s3 = "Hel" + "lo";
String s4 = "Hel" + new String("lo");
String s5 = new String("Hello");
String s6 = s5.intern();
System.out.println(s1 == s2);  // true
System.out.println(s1 == s3);  // true
System.out.println(s1 == s4);  // false
System.out.println(s4 == s5);  // false
System.out.println(s1 == s6);  // true

Explanation

The references of s1, s2, s3, and s6 all point to the same pooled object, while s4 and s5 do not. Here is why:

  • s1 == s2 is true because both are the same literal "Hello", so the compiler hands out the same pooled reference.
  • s1 == s3 is true because "Hel" + "lo" concatenates two compile-time constants. The compiler folds it into the literal "Hello", so it lands in the pool as well.
  • s1 == s4 is false because s4 involves new String("lo"), so the concatenation happens at runtime and produces a brand-new object on the heap instead of a pooled one.
  • s4 == s5 is false because every new String(...) creates a distinct heap object.
  • s1 == s6 is true because s5.intern() returns the pooled instance equal to s5 (see below).

Objects created with new String(...) live in the heap, while interned string constants live in the string pool.

Note: Where the string pool itself lives has changed across JVM versions. Up to Java 6 it sat in the Method Area (PermGen). Java 7 moved the pool into the heap, and Java 8 removed PermGen altogether. So on any modern JVM, both the pool and new String(...) objects reside in the heap, just in different regions.

Something about intern()

When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool, and a reference to this String object is returned.

References