zl程序教程

您现在的位置是:首页 >  其它

当前栏目

Java8新特性之字符串去重介绍

介绍 字符串 特性 java8
2023-06-13 09:15:46 时间

8月19日,Oracle发布了JDK8u20,JDK8u20包含很多新特性,比如Java编译器更新、支持在运行时通过API来修改MinHeapFreeRatio和MaxHeapFreeRatio参数、新的GC调优指南文档。不过在众多新特性中,最令人期待的还属字符串去重(StringDeduplication)。如何减少内存占用一直是一个永恒的话题,而在Java应用中,经常会看到String对象会占用应用30%的内存,它是Java中最常用的对象之一。新的字符串去重特性可以帮助减少应用中String对象的内存占用,目前该特性只适用于G1垃圾收集器,并且默认不被开启。

FabianLange解释了字符串去重特性的实现方式:

复制代码代码如下:


垃圾收集器会在访问String对象时对其字符数组进行标记,并将String的哈希值以及弱引用保存到一个数组中。当垃圾收集器发现另一个具有相同哈希值的String对象时,它就会逐字符比对这两个对象。如果他们完全匹配,那其中一个String就会被修改指向到另一个String的字符数组。由于第一个字符数组已经不再被引用,所以它也就可以被回收了。垃圾收集器会尽量减少整个操作的开销,比如某个String对象扫描未发现有重复,那接下来的一段时间内它不会再被检查。

紧接着,FabianLange通过代码的方式解释了字符串去重特性的神奇效果。首先使用Java8Update20通过参数-Xmx256m-XX:+UseG1GC运行以下代码:

复制代码代码如下:

publicclassLotsOfStrings{

 privatestaticfinalLinkedList<String>LOTS_OF_STRINGS=newLinkedList<>();

 publicstaticvoidmain(String[]args)throwsException{
   intiteration=0;
   while(true){
     for(inti=0;i<100;i++){
       for(intj=0;j<1000;j++){
         LOTS_OF_STRINGS.add(newString("String"+j));
       }
     }
     iteration++;
     System.out.println("SurvivedIteration:"+iteration);
     Thread.sleep(100);
   }
 }
}

代码会在30次循环之后因OutOfMemoryError异常而结束运行。在使用参数-XX:+UseStringDeduplication-XX:+PrintStringDeduplicationStatistics开启字符串去重特性后,程序可以多运行一段时间。通过JVM的日志也可以详细了解整个去重过程的详细信息。请读者自行测试。

最后,FabianLange还解释了字符串去重与字符串驻留的区别,它们很相似,除了字符串驻留重用了整个的String实例,而字符串去重只是针对String的字符数组。

(全文完)