Java 9 comes with several enhancements on how Strings are being handled, promising to improve the performance of your applications.

Storing Strings

If you examine the memory being used by your Java application, you will most likely notice that a significant amount of the heap is allocated by String objects.

Up to Java 8, each String is represented internally as a char[] (that is a char array).

The char data type is a single Unicode character that takes up 2 bytes of memory. It has a minimum value of ‘\u0000’ (=0) and a maximum value of ‘\uffff’ (=65535).

Strings in Java 9

When we store a Unicode character, such as the Greek character ‘α’ (=’\u03b1’), then we are truly making use of both bytes being allocated for that char.

However, when we store a Latin character, such as ‘a’ (=’\u0061’), then the first byte allocated for that char is filled with zeros, and is thus being effectively unused.

Wouldn’t it be great if Java didn’t allocate 2 bytes for each Latin character, but allocated only 1 byte instead?

In Java 9, the String class has been changed to store characters in a byte[] (instead of a char[]). This change in the underlying data structure of String allows a fine grained allocation of memory, depending on the type of characters:

  • for Strings containing Unicode characters, 2 bytes are being allocated for each character, as previously.
  • for Strings containing only Latin characters, 1 byte is allocated for each character, thus saving memory compared to previous releases of Java.

Concatenating Strings

Up to Java 8, the Java compiler recognizes any String concatenations in the source code, and translates them into chains of StringBuilder::append.

In Java 9, each String concatenation is translated into a call to invokedynamic, as described in JDK Enhancement Proposal 280.

There are several String concatenation strategies available in Java 9, with each one of them employing a different technique to compute the size of the resulting/concatenated String. One of the strategies that stands out for its performance is MH_INLINE_SIZED_EXACT, which takes advantage of private Java APIs in order to perform the String concatenation.

Performance Improvement

The allocation rate is a key performance metric in Java applications; it is the amount of memory allocated per time unit, and it is typically measured in MB/sec.

Thanks to the reduced memory footprint of String objects in Java 9, your applications are expected to have a lower allocation rate; this means that the Garbage Collector will be called less frequently to clean the memory. Given that the Garbage Collector pauses your applications while it is cleaning the memory, you will likely experience a decrease in the frequency and/or the duration of pauses for your applications. It is therefore assumed that your applications will have a higher throughput, and lower latency in Java 9.

As stated here, “footprint and performance improvements up to 10%” have been measured for several applications in Java 9.

How much faster will your applications run with Java 9? There is only one way to find out: download Java 9, and measure the performance of your applications!