Включена ли функция дедупликации строк в сборщике мусора G1 по умолчанию?

JEP 192. Дедупликация строк в G1, реализованная в Java 8 В обновлении 20 добавлена ​​новая функция дедупликации строк:

Сократите набор динамических данных кучи Java, улучшив сборщик мусора G1, чтобы дублированные экземпляры String автоматически и непрерывно дедуплицировались.

На странице JEP упоминается, что опция командной строки UseStringDeduplication (bool) позволяет включить или отключить функцию дедупликации. Но страница JEP не заходит так далеко, чтобы указать значение по умолчанию.

Feature Включена или выключена функция дедупликации по умолчанию в сборщике мусора G1 в комплекте с Java 8 и Java 9?

➠ Есть ли метод "получения", чтобы проверить текущие настройки во время выполнения?

Я не знаю, где искать документацию за пределами страницы JEP.

По крайней мере в реализациях Java 9, оборудованных HotSpot, сборщик мусора G1 включен по умолчанию. Этот факт вызвал этот вопрос сейчас. Более подробную информацию об интернировании и дедупликации строк смотрите в презентации 2014-10 Алексея Шипилева в 29:00.

2 ответа

Решение

Дедупликация строк отключена по умолчанию

Для версий Java 8 и Java 9, показанных ниже, UseStringDeduplication является false (отключено) по умолчанию.

Один из способов проверить настройку функции: перечислить все последние флаги для 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.

Несмотря на то, что Jigar точно предоставил способ узнать флаги и статистику JVM, все же приведу ссылку на некоторые полезные документы, касающиеся этой части вопроса:

Я не знаю, где искать документацию за пределами страницы JEP.

В JDK 9 сборщик мусора по умолчанию - G1, когда сборщик мусора не указан явно.

  • Инструмент Java, который детализирует использование флага

    -XX:+UseStringDeduplication
    

Включает дедупликацию строк. По умолчанию эта опция отключена. Чтобы использовать эту опцию, вы должны включить сборщик мусора в первую очередь (G1).

Дедупликация строк уменьшает объем занимаемой памяти объектов String в куче Java благодаря использованию того факта, что многие объекты String идентичны. Вместо каждого объекта String, указывающего на свой собственный массив символов, идентичные объекты String могут указывать и использовать один и тот же массив символов.


Также обращаясь к открытому вопросу, если

Java 9 не имеет возможности печатать статистику дедупликации строк.

В JEP 158: реализация Unified JVM Logging в Java9 флаги сборщика мусора помечаются как устаревшие, и используется альтернативный способ их отслеживания -Xlog особенность. Подробный список замены для преобразования GC Logging Flags в Xlog приведен здесь. Один из которых предлагает заменить

PrintStringDeduplicationStatistics  =>   -Xlog:stringdedup*=debug
Другие вопросы по тегам