Java String Constant Pool
How String Values Are Stored in Memory
There are two ways to create a String in Java.
- Using the
newoperator - 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.