聊聊G1 GC的String Deduplication

本文主要研究一下G1 GC的String Deduplicationjava

-XX:+UseStringDeduplication

  • jdk8u20給G1 GC帶來了String Deduplication特性來將相同的字符串指向同一份數據,來減小重複字符串的內存開銷
  • 該特性默認是關閉的,能夠使用-XX:+UseStringDeduplication來開啓(前提是使用-XX:+UseG1GC)
  • 具體的實現大體是JVM會記錄char[]的weak reference及hash value,當找到一個hash code相同的String時,就會挨個char進行比較,當全部都match,那麼其中一個String就會修改指針指向另外一個String的char[],這樣前者的char[]就能夠被回收

實例

實驗代碼

@Test
    public void testG1StringDeduplication() throws InterruptedException {
        List<String> data = IntStream.rangeClosed(1,10000000)
                .mapToObj(i -> "number is " + ( i % 2 == 0 ? "odd" : "even"))
                .collect(Collectors.toList());
        System.gc();
        long bytes = RamUsageEstimator.sizeOfAll(data);
        System.out.println("string list size in MB:" + bytes*1.0/1024/1024);
        System.out.println("used heap size in MB:" + ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed()*1.0/1024/1024);
        System.out.println("used non heap size in MB:" + ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getUsed()*1.0/1024/1024);

    }

關閉StringDeduplication

-XX:+UseG1GC -XX:-UseStringDeduplication
輸出以下:
string list size in MB:586.8727111816406
used heap size in MB:831.772346496582
used non heap size in MB:6.448394775390625
  • 整個jvm heap佔用了約831MB,其中string list佔用了約586MB

開啓StringDeduplication

-XX:+UseG1GC -XX:+UseStringDeduplication
輸出以下:
string list size in MB:296.83294677734375
used heap size in MB:645.0970153808594
used non heap size in MB:6.376350402832031
  • 整個jvm heap佔用了約645MB,其中string list佔用了約296MB

小結

  • jdk8u20給G1 GC帶來了String Deduplication特性來將相同的字符串指向同一份數據,來減小重複字符串的內存開銷
  • 該特性默認是關閉的,能夠使用-XX:+UseStringDeduplication來開啓(前提是使用-XX:+UseG1GC)
  • 在有大量重複string的前提下,使用G1 GC開啓String Deduplication確實可以節省必定的內存,能夠節約20%左右的內存,不過這個是理想的狀況,由於普通應用裏頭的string重複的可能很少

doc

相關文章
相關標籤/搜索