JDK 9 introduced compact strings to reduce the space required for strings containing only Latin1 characters. To accomplish this feature, the value field of String was changed from char[] to byte[]. The side effect of this change is that the number of characters represented by a string containing unicode characters was reduced by half.
import java.util.Arrays;
public class Test {
// Run with -Xmx16g
public static void main(String[] args) {
char[] chars = new char[Integer.MAX_VALUE - 2];
Arrays.fill(chars, '\u2022');
String string = new String(chars);
System.out.println(string.length());
}
}
JDK8 output:
2147483645
JDK9 output:
Exception in thread "main" java.lang.OutOfMemoryError: UTF16 String size is 2147483645, should be less than 1073741823
at java.base/java.lang.StringUTF16.newBytesFor(StringUTF16.java:46)
at java.base/java.lang.StringUTF16.toBytes(StringUTF16.java:148)
at java.base/java.lang.String.<init>(String.java:3023)
at java.base/java.lang.String.<init>(String.java:249)
at Test.main(test.java:7)
No information was provided in the release notes for this significant change in behaviour.
import java.util.Arrays;
public class Test {
// Run with -Xmx16g
public static void main(String[] args) {
char[] chars = new char[Integer.MAX_VALUE - 2];
Arrays.fill(chars, '\u2022');
String string = new String(chars);
System.out.println(string.length());
}
}
JDK8 output:
2147483645
JDK9 output:
Exception in thread "main" java.lang.OutOfMemoryError: UTF16 String size is 2147483645, should be less than 1073741823
at java.base/java.lang.StringUTF16.newBytesFor(StringUTF16.java:46)
at java.base/java.lang.StringUTF16.toBytes(StringUTF16.java:148)
at java.base/java.lang.String.<init>(String.java:3023)
at java.base/java.lang.String.<init>(String.java:249)
at Test.main(test.java:7)
No information was provided in the release notes for this significant change in behaviour.