web-dev-qa-db-ja.com

G1ガベージコレクターの文字列重複排除機能はデフォルトで有効になっていますか?

JEP 192:G1での文字列重複排除 Java 8 Update20で実装文字列重複排除機能:

Stringの重複インスタンスが自動的かつ継続的に重複排除されるように、G1ガベージコレクターを拡張して、Javaヒープライブデータセットを削減します。

JEPページには、コマンドラインオプションUseStringDeduplication (bool)を使用すると、重複排除機能を有効または無効にできると記載されています。しかし、JEPページはデフォルトを示すまでは行きません。

➠G1ガベージコレクターの重複排除機能は、デフォルトでJava 8およびJava 9)にバンドルされていますか?

➠実行時に現在の設定を確認するための「ゲッター」メソッドはありますか?

JEPページ以外のドキュメントを探す場所がわかりません。

少なくとも HotSpot -装備されたJava 9、 G1ガベージコレクターデフォルトで有効 。その事実が今この質問を促しました。文字列のインターンと重複排除の詳細については、 Aleksey Shipilevによるこの2014-10プレゼンテーション を参照してください。 = 29:00に。

14
Basil Bourque

デフォルトでは、文字列重複排除off

以下に示すJava 8およびJava 9のバージョンの場合、UseStringDeduplicationはデフォルトでfalse(無効)です。

機能設定を確認する1つの方法: JVMのすべての最終フラグをリストアップ そしてそれを探します。

ビルド1.8.0_131-b11

    $ Java -XX:+UseG1GC  -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | grep -i 'duplicat'
     bool PrintStringDeduplicationStatistics        = false                               {product}
    uintx StringDeduplicationAgeThreshold           = 3                                   {product}
     bool StringDeduplicationRehashALot             = false                               {diagnostic}
     bool StringDeduplicationResizeALot             = false                               {diagnostic}
     bool UseStringDeduplication                    = false                               {product}
Java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

ビルド9 + 18

    $ Java -XX:+UseG1GC  -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | grep -i 'duplicat'
    uintx StringDeduplicationAgeThreshold          = 3                                        {product} {default}
     bool StringDeduplicationRehashALot            = false                                 {diagnostic} {default}
     bool StringDeduplicationResizeALot            = false                                 {diagnostic} {default}
     bool UseStringDeduplication                   = false                                    {product} {default}
Java version "9"
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)

それをテストする別の方法は

package jvm;

import Java.util.ArrayList;
import Java.util.List;

public class StringDeDuplicationTester {

    public static void main(String[] args) throws Exception {
        List<String> strings = new ArrayList<>();
        while (true) {
            for (int i = 0; i < 100_00; i++) {
                strings.add(new String("String " + i));
            }
            Thread.sleep(100);
        }
    }
}

明示的に指定せずに実行します。

$ Java  -Xmx256m -XX:+UseG1GC -XX:+PrintStringDeduplicationStatistics jvm.StringDeDuplicationTester
Exception in thread "main" Java.lang.OutOfMemoryError: Java heap space
    at jvm.StringDeDuplicationTester.main(StringDeDuplicationTester.Java:12)

明示的にオンにして実行します。

$ Java  -Xmx256m -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics jvm.StringDeDuplicationTester
[GC concurrent-string-deduplication, 5116.7K->408.7K(4708.0K), avg 92.0%, 0.0246084 secs]
   [Last Exec: 0.0246084 secs, Idle: 1.7075173 secs, Blocked: 0/0.0000000 secs]
      [Inspected:          130568]
         [Skipped:              0(  0.0%)]
         [Hashed:          130450( 99.9%)]
         [Known:                0(  0.0%)]
         [New:             130568(100.0%)   5116.7K]
      [Deduplicated:       120388( 92.2%)   4708.0K( 92.0%)]
         [Young:                0(  0.0%)      0.0B(  0.0%)]
         [Old:             120388(100.0%)   4708.0K(100.0%)]
   [Total Exec: 1/0.0246084 secs, Idle: 1/1.7075173 secs, Blocked: 0/0.0000000 secs]
      [Inspected:          130568]
         [Skipped:              0(  0.0%)]
         [Hashed:          130450( 99.9%)]
         [Known:                0(  0.0%)]
         [New:             130568(100.0%)   5116.7K]
      [Deduplicated:       120388( 92.2%)   4708.0K( 92.0%)]
         [Young:                0(  0.0%)      0.0B(  0.0%)]
         [Old:             120388(100.0%)   4708.0K(100.0%)]
   [Table]
      [Memory Usage: 264.9K]
      [Size: 1024, Min: 1024, Max: 16777216]
      [Entries: 10962, Load: 1070.5%, Cached: 0, Added: 10962, Removed: 0]
      [Resize Count: 0, Shrink Threshold: 682(66.7%), Grow Threshold: 2048(200.0%)]
      [Rehash Count: 0, Rehash Threshold: 120, Hash Seed: 0x0]
      [Age Threshold: 3]
   [Queue]
      [Dropped: 0]
[GC concurrent-string-deduplication, deleted 0 entries, 0.0000008 secs]
...
output truncated

:この出力はbuild 1.8.0_131-b11からのものです。 Java 9には文字列重複排除統計を出力するオプションがないようです。潜在的なバグ?いいえ。統合ログが強制終了されましたこの特定のオプション。

$ Java  -Xmx256m -XX:+UseG1GC -XX:+PrintStringDeduplicationStatistics -version
Unrecognized VM option 'PrintStringDeduplicationStatistics'
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
16
Jigar Joshi

Jigar は、JVMのフラグと統計を知る方法を正確に提供していますが、質問のこの部分に対処するいくつかの有用なドキュメントにリンクしています。

JEPページ以外のドキュメントを探す場所がわかりません。

JDK 9では、ガベージコレクタが明示的に指定されていない場合、デフォルトのガベージコレクタはG1です。

  • Javaツール フラグの使用法の詳細

    -XX:+UseStringDeduplication
    

文字列の重複排除を有効にします。 デフォルトでは、このオプションは無効になっています。このオプションを使用するには、ガベージファースト(G1)ガベージコレクタを有効にする必要があります。

文字列の重複排除は、多くの文字列オブジェクトが同一であるという事実を利用して、Javaヒープ上の文字列オブジェクトのメモリフットプリントを削減します。各文字列オブジェクトが独自の文字配列を指す代わりに、同一の文字列オブジェクト同じ文字列をポイントして共有できます。


未解決の質問にも対処する

Java 9には、文字列重複排除統計を出力するオプションがありません。

Java9でのJEP 158:Unified JVM Logging実装では、ガベージコレクターフラグはレガシーとしてマークされ、それらをトレースする別の方法は-Xlog機能。 GCロギングフラグをXlogに変換するための代替の詳細なリストがリストされています ここ 。そのうちの1つは交換を提案します

PrintStringDeduplicationStatistics  =>   -Xlog:stringdedup*=debug
12
Naman