コンパクト文字列 のJDK9での圧縮文字列に対する利点は何ですか?
XX:+ UseCompressedStringsとCompact Stringsは異なるものです。
UseCompressedStrings
は、ASCIIのみがbyte[]
に変換できるストリングでしたが、これはデフォルトでオフでした。ただし、フラグ自体ではなく、組み込みです。
Java-9文字列がUTF-16エンコーディングでchar[]
として内部的に保存されるまで。 Java-9以降では、byte[]
として保存されます。どうして?
ISO_LATIN_1
では、各文字を1バイト(8ビット)でエンコードできるのに対し、これまで使用されていたもの(16ビット、使用されない場合は各8ビット)であるためです。これはISO_LATIN_1
に対してonlyで動作しますが、とにかく使用される文字列の大部分です。
したがって、これはスペース使用量に対して行われます。
以下は、物事をより明確にするための小さな例です。
class StringCharVsByte {
public static void main(String[] args) {
String first = "first";
String russianFirst = "первыи";
char[] c1 = first.toCharArray();
char[] c2 = russianFirst.toCharArray();
for (char c : c1) {
System.out.println(c >>> 8);
}
for (char c : c2) {
System.out.println(c >>> 8);
}
}
}
最初のケースでは、ゼロのみを取得します。つまり、最上位の8ビットはゼロです。 2番目の場合、ゼロ以外の値になります。つまり、最上位8から少なくとも1ビットが存在することを意味します。
つまり、文字列を文字の配列として内部に格納すると、実際には各文字の半分を無駄にする文字列リテラルが存在します。このため、実際には多くのスペースを浪費する複数のアプリケーションがあります。
10個のLatin1文字から作成された文字列がありますか? 80ビット、つまり10バイトを失っただけです。この文字列圧縮を緩和するために行われました。そして今、これらの文字列にスペースの損失はありません。
内部的には、これは非常に素晴らしいことも意味します。 LATIN1
とUTF-16
である文字列を区別するために、フィールドcoder
があります。
/**
* The identifier of the encoding used to encode the bytes in
* {@code value}. The supported values in this implementation are
*
* LATIN1
* UTF16
*
* @implNote This field is trusted by the VM, and is a subject to
* constant folding if String instance is constant. Overwriting this
* field after construction will cause problems.
*/
private final byte coder;
これに基づいて、length
の計算方法が異なります。
public int length() {
return value.length >> coder();
}
StringがLatin1のみの場合、コーダーはゼロになるため、値の長さ(バイト配列)はcharsのサイズになります。 Latin1以外の場合は2で割ります。
Compact Stringsは両方の長所を備えています。
OpenJDKドキュメントで提供される定義に見られるように:
新しいStringクラスは、文字列の内容に基づいて、ISO-8859-1/Latin-1(文字あたり1バイト)またはUTF-16(文字あたり2バイト)としてエンコードされた文字を格納します。エンコーディングフラグは、使用されているエンコーディングを示します。
@Eugeneで述べたように、ほとんどの文字列はLatin-1形式でエンコードされ、文字ごとに1バイトを必要とするため、現在のStringクラスの実装で提供される2バイトスペース全体を必要としません。
新しいStringクラスの実装は、UTF-16 char array
からa byte array
に移行しますプラスエンコードフラグフィールド。追加のencoding fieldは、文字がUTF-16形式またはLatin-1形式を使用して保存されているかどうかを示します。
これにより、必要に応じてUTF-16形式で文字列を保存することもできます。また、これはJava 6の圧縮文字列とJava 9の圧縮文字列の違いの主なポイントになります- byte [] arrayのみがストレージに使用され、pure ASCIIとして表されました。
圧縮された文字列(-XX:+ UseCompressedStrings)
これは、Java 6Update 21で導入されたオプション機能でした-バイトでUS-ASCII文字列のみをエンコードすることでパフォーマンスを向上させる SPECjbb 文字ごと。
この機能は、-XX
フラグ(-XX:+UseCompressedStrings
)によって有効にできます。有効にすると、String.value
はオブジェクト参照に変更され、7ビットのUS-ASCII文字のみを含む文字列の場合はbyte[]
、またはchar[]
を指すようになります。
後で、Java 7でメンテナンスが高く、テストが難しいため削除されました。
コンパクト文字列
これは、メモリ効率の良い文字列を構築するためにJava 9で導入された新しい機能です。
Java 9より前、文字列クラスは文字をchar配列に格納し、各文字に2バイトを使用していましたが、Java 9 byte[]
(文字ごとに1バイト)またはchar[]
(文字ごとに2バイト)、文字列の内容とエンコードフラグフィールドに基づきます。文字列文字がLatin-1
型の場合文字がbyte[]
タイプの場合はUTF-16
が使用され、そうでない場合はchar[]
が使用されますエンコードフラグは、使用されるエンコードを示します。