Understanding the Java String.intern() Memory Model

Calling string.intern() in Java first looks up the corresponding string in the string constant pool; if it doesn't exist, the string is created in the pool and then returned.

  • Ryan
  • 2 min read
/images/posts/java-string-pool.png

As you know, calling string.intern() in Java first looks up the corresponding string in the string constant pool; if the string does not exist, it is created in the pool and then returned.

The string constant pool is a fixed-size HashMap whose default bucket count is 1009; starting from Java 7u40, this default was increased to 60013. In Java 6, the string constant pool was located in the Perm space, and starting from Java 7 it was moved to the Heap space. Below, we use a test program to look at the memory allocation of the string constant pool under the two different versions, Java 6 and Java 7.

Test program

public class StringPoolTest {

    public void testStringPoolWithLongString(){
        long i=0;
        while(true){
            String longString = "This is a very long string, very very long string to test the gc behavior of the string constant pool"+i;
            longString.intern();
            i++;
        }
    }

    public static void main(String[] args){
        StringPoolTest stringPoolTest = new StringPoolTest();
        stringPoolTest.testStringPoolWithLongString();
    }
}

The test program is simple: an infinite loop that generates a unique string by incrementing the variable i, then starts via the main function.

Java 6

We run this program with JDK 1.6.0_29 and monitor it with Java VisualVM. We can see that the Perm area keeps triggering GC, from which we conclude that although the string constant pool is placed in the Perm space, when the Perm space is nearly full, the JVM will reclaim useless strings in the string constant pool.

Java 7

Next, we switch to JDK 1.7.0_67 and rerun the program. We can see that the Perm area memory allocation curve is very smooth, with no memory allocation activity.

But in the Heap space, new objects are constantly created and GC is triggered repeatedly.

Conclusion

Because the Perm area is limited in size — usually only tens of MB — it is not recommended to use String.intern() extensively under Java 6. The performance tests in this article show that heavy use of intern() under Java 6 leads to a significant performance degradation and can even cause OOM errors. But starting from Java 7, the string constant pool was moved to the Heap space, whose size is limited only by the machine’s actual memory. Therefore, using String.intern() under Java 7 can more effectively reduce the memory footprint of duplicate String objects.

Frequently Asked Questions

What does String.intern() do?
String.intern() looks up the string in the string constant pool. If an equal string already exists, it returns the pooled reference. If not, it adds the string to the pool and returns the reference.
Should I use String.intern() in production?
Under Java 7+, the string constant pool lives in the Heap, so intern() is safer. However, excessive use can still cause performance issues due to pool contention. For most use cases, a HashMap or ConcurrentHashMap is a better choice for string deduplication.
Why does Java 6 behave differently from Java 7 for intern()?
In Java 6, the string constant pool was in PermGen (typically only tens of MB). Heavy intern() usage could easily cause OutOfMemoryError. Starting from Java 7, the pool was moved to the Heap, which is much larger and only bounded by physical memory.

Written by : Ryan

Writing about distributed systems, AI engineering, and production internals.

Recommended for You

The Implementation Details of hashCode()

The Implementation Details of hashCode()

A deep dive into the implementation of Java's hashCode() method, from class loading to hash collision handling.

The Real Value of an int Variable Starting with 0 in Java

The Real Value of an int Variable Starting with 0 in Java

In Java, an int literal starting with 0 is interpreted as an octal (base-8) number. This article explains how Java represents octal integers.