Java String Constant Pool

How Java String values are stored in memory

How String Values Are Stored in Memory

There are two ways to create a String in Java.

  • Using the new operator
  • Using a literal

The differences between the two declaration methods are as follows.

new declaration Literal declaration
Storage location Stored in the “Heap” area Stored in the “String constant pool”
Speed Slower than literal declaration Faster than new declaration
Comparing identical strings Must use the .equals method to get the same result Can be compared with the == operator

If the string exists in the “String constant pool”, its address value is returned. If it does not exist, it is stored and a new address value is returned. The string constant pool exists in the Perm area, but its location changed starting with Java 7.

If the same string is created in the two ways above and compared with the == operator and .equals(), the following result is produced.

public static void main(String[] args) {
    String a = "apple";
    String b = "apple";
    String c = new String("apple");
    
    System.out.println(a == b); // true
    System.out.println(a == c); // false
    
    System.out.println(a.equals(b)); // true
    System.out.println(a.equals(c)); // true
}

Change in String Constant Pool Location

Until Java 6, the String constant pool was located in the Perm area. In Java 7, it was moved from the Perm area to the Heap area. The reason was the OutOfMemoryException problem.

The Perm area has a fixed size and does not expand at runtime. Although the size of the Perm area can be increased, its size still does not change at runtime. Therefore, until Java 6, calling the String intern() method could cause an OutOfMemoryException, and there was no way to control that part, so it was generally better not to use it.

For this reason, Oracle engineers moved the string constant pool in Java 7 from the Perm area to the Heap area. What benefit does this provide? Every string in the string constant pool can now become a GC target.

The size of the String constant pool can be specified with the -xx:StringTableSize option. This should be set to a prime number such as 1,000,003, not a number like 1,000,000. It is related to hashCode performance, and the Java Performance Tuning Guide article explains the details.

If you actively use the intern() method, you should set -xx:StringTableSize higher than the default value (1009). Otherwise, performance can degrade to the level of a linked list.

Reference