19 августа Oracle выпустила JDK 8u20. JDK 8u20 включает в себя множество новых функций, таких как обновления компилятора Java, поддержку изменения параметров MinHeapFreeRatio и MaxHeapFreeRatio через API во время выполнения, а также новые документы с руководством по настройке GC. Однако среди множества новых функций наиболее ожидаемой является дедупликация строк. Как уменьшить использование памяти всегда было вечной темой. В Java-приложениях часто можно увидеть, что объект String занимает 30% памяти приложения. Это один из наиболее часто используемых объектов в Java. Новая функция дедупликации строк может помочь уменьшить объем памяти, занимаемый объектами String в приложениях. В настоящее время эта функция доступна только для сборщика мусора G1 и не включена по умолчанию.
Фабиан Ланге объясняет, как реализована дедупликация строк:
Скопируйте код кода следующим образом:
Сборщик мусора пометит массив символов объекта String при доступе к нему и сохранит хеш-значение объекта String и слабую ссылку в массиве. Когда сборщик мусора находит другой объект String с тем же значением хеш-функции, он сравнивает два объекта посимвольно. Если они точно совпадают, одна строка будет изменена, чтобы указывать на массив символов другой строки. Поскольку на первый массив символов больше нет ссылок, его можно переработать. Сборщик мусора попытается снизить стоимость всей операции. Например, если объект String просканирован и дубликатов не обнаружено, он не будет проверяться повторно в следующий период времени.
Далее Фабиан Ланге объяснил волшебный эффект дедупликации строк с помощью кода. Сначала запустите следующий код, используя Java 8 Update 20 с параметрами -Xmx256m -XX:+UseG1GC:
Скопируйте код кода следующим образом:
общественный класс MuchOfStrings {
частный статический окончательный LinkedList<String> LOTS_OF_STRINGS = новый LinkedList<>();
public static void main(String[] args) выдает исключение {
int итерация = 0;
в то время как (истина) {
для (int я = 0; я <100; я++) {
for (int j = 0; j < 1000; j++) {
LOTS_OF_STRINGS.add(новая строка("String " + j));
}
}
итерация++;
System.out.println("Выжившая итерация: " + итерация);
Thread.sleep(100);
}
}
}
Код завершится из-за исключения OutOfMemoryError после 30 циклов. После использования параметров -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics для включения функции дедупликации строк программа может работать в течение более длительного периода времени. Вы также можете узнать больше о деталях всего процесса дедупликации из журналов JVM. Читателям предлагается проверить это самостоятельно.
Наконец, Фабиан Ланге также объяснил разницу между дедупликацией строк и резидентностью строки. Они очень похожи, за исключением того, что резидентность строки повторно использует весь экземпляр String, тогда как дедупликация строки нацелена только на массив символов String.
(Полный текст заканчивается)