Friday, July 15, 2016

String pool in Java is a pool of String literals and interned Strings in JVM for efficient use of String object. Since String is immutable in Java, it makes sense to cache and shares them in JVM. The String pool has gone through an important change in Java 7 release when it was relocated from PermGen space to heap space. Till Java 1.6, interned String and literals are stored in the PermGen space of JVM memory, which was a fixed size area for storing class metadata. The biggest issue of having String pool in PermGen is the small and fixed size of PermGen space. In some JVM it ranges from 32M to 96M, which is quite small for a large program. Since String is extensively used in both small and large Java application, Java designers thought String pool is the best way optimize the use of String object in Java.
Btw, you can also change the size of PermGen space using JVM parameters -XX+PermGenSize, it is still fixed. Such limitation requires very restricted use of String.intern() method, you would better not using String.intern() method in a loop or at large scale to avoid java.lang.OutOfMemoryError : PermGen space.

By relocating String pool to heap space, you gain the benefit of large memory space. String pool can grow and shrink much more smoothly than they were in PermGen space. Since String literals and interned String are also garbage collected, the size of the pool will grow and shrink depending upon the state of your program.

String pool changes in Java 7

The JDK 7 introduces many changes e.g. String in the switch case, try-with-resources, better exception handling, and new File API (see the full list here), the change which mostly gone unnoticed but has a significant impact was the change made to String class and the String pool itself.

The default size of String pool has increased on Java 7 update 40 release. The String pool is implemented using a HashMap in Java and default size of the table in Java 6 was 1009 , which was further increased to 60013 in Java 7. See Java Performance The Definitive Guide by Scott Oaks to learn more about Java 7 changes which affect the performance of Java applications.

You can also customize string pool size using -XX:StringTableSize parameter. If you do provide a custom size for String pool, consider giving a prime number. Depending upon your Java application, having a String pool of 1 million entries may not be a bad idea. Though default size of String pool, 60013 is also good enough for many Java programs and hence retained in Java 8 as well.

If you are not sure about String pool usage then you can also print string pool statistics using -XX:+PrintStringTableStatistics JVM option. It will print string pool usage data once your program finished execution.

Due to this relocation of String pool from PermGen memory space to heap space, the String.intern() method, which is used to intern a String object and store inside string pool for further reuse has now become even more useful. You can intern a large number of String than before. You are only limited by your JVM heap size as far as String pool goes.

In summary here, is the important difference in String pool in Java 6 and 7:

String pool is relocated to Java heap space from PermGen space.

The default size of String pool is increased to 600013 entries from 1009 in Java 6.

The -XX:StringTableSize JVM option is provided to specify the size of String pool.

Apart from that String class is also changed e.g. now the char[] is not referenced when you create substring, instead a new array is created with only necessary data required by substring method, as shown below:

That's all about the difference between String pool in Java 6 and 7. It is one of the important details which many Java developer doesn't know but it can affect both performance and stability of your Java application. If you are still not running on Java 7, then first steps are to switch to Java 7 runtime and then try for Java SE 8 upgrade as Java 9 is not very far away :-).

Here new "string instance" will be created in Heap at some reference say 1234 and, the literal("Java") and string object reference(1234) will be stored in string constant pool. Is my understanding correct?