8 月 19 日に、Oracle は JDK 8u20 をリリースしました。JDK 8u20 には、Java コンパイラの更新、実行時の API を介した MinHeapFreeRatio および MaxHeapFreeRatio パラメータの変更のサポート、新しい GC チューニング ガイド ドキュメントなど、多くの新機能が含まれています。ただし、多くの新機能の中で最も期待されているのは文字列重複排除です。メモリ使用量を削減する方法は常に永遠のテーマであり、String オブジェクトは Java で最も一般的に使用されるオブジェクトの 1 つです。新しい文字列重複排除機能は、アプリケーション内の String オブジェクトのメモリ フットプリントを削減するのに役立ちます。現在、この機能は G1 ガベージ コレクターでのみ利用可能であり、デフォルトでは有効になっていません。
Fabian Lange が文字列重複排除の実装方法を次のように説明しています。
次のようにコードをコピーします。
ガベージ コレクターは、String オブジェクトがアクセスされるとその文字配列をマークし、String のハッシュ値と弱参照を配列に保存します。ガベージ コレクターは、同じハッシュ値を持つ別の String オブジェクトを見つけると、2 つのオブジェクトを文字ごとに比較します。それらが正確に一致する場合、一方の文字列は、もう一方の文字列の文字配列を指すように変更されます。最初の文字配列は参照されなくなるため、再利用できます。ガベージ コレクターは、操作全体のコストを削減しようとします。たとえば、String オブジェクトがスキャンされて重複が見つからなかった場合、次の期間には再度チェックされません。
次に、Fabian Lange 氏は、コードによる文字列重複排除の魔法のような効果について説明しました。まず、Java 8 Update 20 を使用し、パラメータ -Xmx256m -XX:+UseG1GC を指定して次のコードを実行します。
次のようにコードをコピーします。
パブリック クラス LotsOfStrings {
プライベート静的最終 LinkedList<String> LOTS_OF_STRINGS = 新しい LinkedList<>();
public static void main(String[] args) throws Exception {
整数反復 = 0;
while (true) {
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 1000; j++) {
LOTS_OF_STRINGS.add(new String("String " + j));
}
}
反復++;
System.out.println("生存した反復: " + 反復);
Thread.sleep(100);
}
}
}
コードは、30 ループ後に OutOfMemoryError 例外により実行を終了します。パラメーター -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics を使用して文字列重複排除機能を有効にすると、プログラムをより長時間実行できるようになります。 JVM ログを通じて、重複排除プロセス全体の詳細について学ぶこともできます。読者はご自身でテストしてください。
最後に、Fabian Lange 氏は、文字列重複排除と文字列常駐の違いについても説明しました。文字列常駐は String インスタンス全体を再利用するのに対し、文字列重複排除は String の文字配列のみを対象とする点が異なります。
(全文終わり)