是否默认启用G1垃圾收集器的String Deduplicationfunction?

JEP 192:在Java 8 Update 20中实现的G1中的字符串重复数据删除添加了新的字符串重复数据删除function:

通过增强G1垃圾收集器来减少Java堆实时数据集,以便自动且连续地对重复的String实例进行重复数据删除。

JEP页面提到命令行选项UseStringDeduplication (bool)允许启用或禁用重复数据删除function。 但是JEP页面并没有指出默认值。

➠与Java 8和Java 9捆绑在一起的G1垃圾收集器中,默认情况下重复数据删除function是打开还是关闭?

➠是否有“getter”方法在运行时validation当前设置?

我不知道在JEP页面之外查找文档的位置。

至少在Java 9的HotSpot配置实现中,默认情况下启用 G1垃圾收集器 。 这个事实现在促成了这个问题。 有关String interning和重复数据删除的更多信息,请参阅Aleksey Shipilev在29:00的2014-10演示文稿 。

字符串重复数据删除默认关闭

对于下面看到的Java 8和Java 9版本,默认情况下UseStringDeduplicationfalse (禁用)。

validationfunction设置的一种方法是: 列出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 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页面之外查找文档的位置。

  • Java9发行说明描述了JEP 248的一个实现:使G1成为默认垃圾收集器

在JDK 9中,当未明确指定垃圾收集器时,默认垃圾收集器为G1。

  • 详细说明标志用法的java工具

     -XX:+UseStringDeduplication 

启用字符串重复数据删除。 默认情况下,禁用此选项 。 要使用此选项,必须启用垃圾优先(G1)垃圾收集器。

字符串重复数据删除通过利用许多String对象相同的事实减少了Java堆上String对象的内存占用。 而不是每个String对象指向它自己的字符数组,相同的String对象可以指向并共享相同的字符数组。


如果还有解决那里的公开问题

Java 9没有打印字符串重复数据删除统计信息的选项。

使用JEP 158: Java9中的统一JVM日志记录实现,垃圾收集器标记被标记为遗留,并且跟踪它们的替代方法是使用-Xlogfunction。 此处列出了将GC Logging Flags转换为Xlog的替换的详细列表。 其中一个建议更换

 PrintStringDeduplicationStatistics => -Xlog:stringdedup*=debug