当前位置: 首页 > 知识库问答 >
问题:

默认情况下,G1垃圾收集器的字符串重复数据删除功能是否启用?

郦良才
2023-03-14

JEP 192:Java 8 Update 20中实现的G1中的字符串重复数据消除新增了字符串重复数据删除功能:

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

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

➠ 在与Java 8和Java 9捆绑的G1垃圾收集器中,重复数据消除功能默认为ON还是OFF?

➠:有没有一个“getter”方法可以在运行时验证当前设置?

我不知道在JEP页面之外哪里可以找到文档。

至少在配备了HotSpot的Java9实现中,G1垃圾收集器在默认情况下处于启用状态。这一事实现在引发了这个问题。有关String实训和重复数据消除的更多信息,请参阅Aleksey Shipilev在29:00发布的2014-10演示文稿。

共有2个答案

凌景辉
2023-03-14

尽管Jigar精确地提供了了解JVM标志和统计数据的方法,但尚未链接到一些解决这部分问题的有用文档:

我不知道在JEP页面之外哪里可以找到文档。

    < Li > Java 9发行说明描述了JEP 248的一个实现:使G1成为缺省的垃圾收集器,代码行为-

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

>

  • 详细描述标志用法的 Java 工具

    -XX:+UseStringDeduplication
    

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

    String消重利用许多String对象是相同的这一事实,减少了Java堆上String对象的内存占用。相同的String对象可以指向并共享相同的字符数组,而不是每个String对象指向自己的字符数组。

    也解决了一个公开的问题

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

    使用JEP 158:Java9中的Unified JVM Logging实现,垃圾收集器标志被标记为遗留标志,跟踪它们的替代方法是使用-Xlog功能。此处列出了将html" target="_blank">GC Logging Flags转换为Xlog的替代方法的详细列表。其中一个建议更换

    PrintStringDeduplicationStatistics  =>   -Xlog:stringdedup*=debug
    

  • 廖绍辉
    2023-03-14

    对于下面看到的 Java 8 和 Java 9 版本,默认情况下,使用字符串重复的(禁用的)。

    验证功能设置的一种方法是:列出 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
    

    < sub >注意:此输出来自< code>build 1.8.0_131-b11。看起来Java 9没有打印字符串重复数据删除统计的选项。潜在bug?不。统一日志记录取消了这一特定选项。

    $ 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.
    
     类似资料:
    • Java8的默认垃圾收集器是什么? 当我检查JMX bean时,他们发现它是新一代的并行收集器,旧一代的旧串行收集器。

    • 这是一个内存数据安全问题。 java垃圾收集是否安全地清除垃圾数据? 显然,在一个数据块被垃圾收集后,我不能再检索它了,但黑客还能通过内存转储来检索数据吗?

    • 问题内容: 由于在Java(与其他语言一样)中由于每个字符占用两个字节而占用大量内存,因此Java 8引入了一项名为 String Deduplication 的新功能,该功能利用了char数组在字符串和final内部的事实,因此JVM会和他们混在一起。 到目前为止,我已经阅读了这个示例,但是由于我不是专业的Java程序员,因此我很难理解这个概念。 它是这样说的, 已经考虑了多种用于字符串复制的策

    • 问题内容: 我正在阅读有关垃圾收集的信息,当我搜索字符串文字垃圾收集时,搜索结果令人困惑。 我需要澄清以下几点: 如果在编译时将字符串定义为文字字符串,那么是否会对其进行垃圾回收? 如果使用实习方法,那么它会被垃圾回收吗?在第1点中,它也将与文字区别对待。 有人提到只有在卸载类时才会对文字进行垃圾回收吗?是否有道理,因为我认为永远不会卸课。 问题答案: 如果在编译时将字符串定义为文字字符串,那么是

    • 问题内容: 简短形式:CMS垃圾收集器似乎无法收集数量不断增加的垃圾;最终,我们的JVM填满,应用程序变得无响应。通过外部工具(JConsole或)强制GC 清理一次。 更新:该问题似乎与JConsole的JTop插件有关。如果我们不运行JConsole,或者在没有JTop插件的情况下运行它,则该行为消失。 (技术说明:我们正在Linux 2.6.9机器上运行32位Sun JDK 1.6.0_07

    • 问题内容: 下面的代码试图删除字符串中所有重复的字符。我不确定代码是否正确。有人可以帮助我处理代码吗(即,字符匹配时实际发生了什么)? 问题答案: 该功能对我来说很好。我已经写了内联评论。希望能帮助到你: